为什么基本类型需要包装类

基本数据类型方便、简单、高效,但泛型不支持、集合元素不支持
不符合面向对象思维
包装类提供很多方法,方便使用,如 Integer 类 toHexString(int i)、parseInt(String s) 方法

Long 或 Integer 如何比较大小?

错误方法
使用==。 因为 Long 与 Ineger 都是包装类型,是对象。 而不是普通类型 long 与 int
使用 equals 方法。因为 equals 方法只能比较同类型的类,例如两个都是 Integer 类型。

正确方法
先使用 longValue()或 intValue()方法来得到他们的基本类型的值然后使用==比较也是可以的。

拆箱与装箱原理

装箱就是将基本数据类型转化为包装类型,那么拆箱就是将包装类型转化为基本数据类型。

1
2
3
4
5
6
7
8
public class Demo{
public static void main(String[] args) {
//自动装箱,底层其实执行了Integer a=Integer.valueOf(10);
Integer a = 10;
//自动拆箱,底层其实执行了int b=a.intValue();
int b = a;
}
}

Integer a = 10;执行代码的时候,系统为我们执行了:Integer a = Integer.valueOf(10);

int b = a;执行代码的时候,系统为我们执行了:int b = a.intValue();

实例:自动拆装箱

实例 1:基本类型与其包装类

1
2
3
4
5
6
7
8
9
10
11
12
public class Demo {
public static void main(String[] args) {
int int1 = 12;
int int2 = 12;
Integer integer1 = new Integer(12);
Integer integer2 = new Integer(12);

System.out.println("int1 == int2 : " + (int1 == int2));
System.out.println("int1 == integer1 : " + (int1 == integer1));
System.out.println("integer1 == integer2 : " + (integer1 == integer2));
}
}

运行结果

1
2
3
int1 == int2         : true
int1 == integer1 : true
integer1 == integer2 : false

Integer 是 int 的封装类,当 Integer 与 int 进行==比较时,Integer 就会拆箱成一个 int 类型,所以还是相当于两个 int 类型进行比较,这里的 Integer 不管是直接赋值,还是 new 创建的对象,只要跟 int 比较就会拆箱为 int 类型,所以就是相等的。

实例 2:自动拆箱引起的异常

首先思考,下边的程序会输出什么

1
2
3
4
5
6
public class Demo {
public static void main(String[] args) {
Integer a = null;
System.out.println(2 == a);
}
}

结果

1
2
Exception in thread "main" java.lang.NullPointerException
at com.example.a.Demo.main(Demo.java:6)

原因:

因为是基本类型与包装类型进行比较,此时会将包装类型自动拆箱,调用a.intValue()获得其基本类型的值,但 a 是 null,所以报空指针异常。

实例 3:基本类型与 Object

1
2
3
4
5
6
7
8
9
10

public class Demo {
public static void main(String[] args) {
Object object = true;
System.out.println(object);
boolean b = (boolean)object;
System.out.println(b);
System.out.println(b == true);
}
}

运行结果

1
2
3
true
true
true

实例:实例化顺序

1
2
3
4
5
6
7
8
9
10
11
12
public class Demo {
public static void main(String[] args) {
int int1 = 12;
Integer integer1 = new Integer(12);

Integer integer2 = new Integer(34);
int int2 = 34;

System.out.println("int1 == integer1 : " + (int1 == integer1));
System.out.println("int2 == integer2 : " + (int2 == integer2));
}
}

执行结果(不影响)

1
2
int1 == integer1     : true
int2 == integer2 : true

实例:区域问题

1
2
3
4
5
6
7
public class Demo {
public static void main(String[] args) {
Integer integer1 = new Integer(12);
Integer integer2 = 12;
System.out.println("integer1 == integer2 : " + (integer1 == integer2));
}
}

执行结果

1
integer1 == integer2 : false

实例:缓存问题

测试代码

1
2
3
4
5
6
7
8
9
10
public class Demo{
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}
}

执行结果

1
2
true
false

Integer 有个缓存,原理如下。

valueOf 源码

1
2
3
4
5
6
7
8
9
// private static class IntegerCache {
// static final int low = -128;
// static final int high = 127;
// }
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

当 i 的值位于[-128,127]的时候,会直接返回 Integer 缓存数组中相应对象的引用,如果 i 大于 127 或小于-128,会重新创建一个 Integer 实例,并返回。

那么第一条式子 a 和 b 的值都在缓存范围内,因此他们指向同一个对象,因此返回 true。c 和 d 的值不在范围内,都是通过 new 创建出来的,因此不是同一个对象,返回 false。

其他包装类的缓存

Byte、Short、Integer、Long、Character 的 valueOf()实现机制类似。

包装类 说明

Byte: 相同值的 Byte 比较永远返回 true。因为 byte 取值范围就是[-128,127]。

Short、Integer、Long 相同值在[-128,127]则返回 true,不在则返回 false
Character 要返回 true,只需保证 i <= 127。因为 char 最小值为 0,本来就大于等于-128。

Float、Double 永远返回 false。因为其永远返回新创建的对象,因为一个范围内的整数是有限的,但是小数却是无限的,无法保存在缓存中。

Boolean 只有两个对象,要么是 true 的 Boolean,要么是 false 的 Boolean,只要 boolean 的值相同,Boolean 就相等。

实例:效率问题

1
2
3
4
5
6
7
8
9
10
11
public class Demo {
public static void main(String[] args) {
long t1 = System.currentTimeMillis();
Long sum = 0L;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
}

上述代码,结果为:6218

如果将 sum 改为 long 型,结果为:624

可见效率差别之大