这里作者举了几个例子,装箱类型,是一个对象,对于Integer来说,默认是null,不是我们想象中的默认 0 ,int 才是默认 0
原文说三个区别:
一、基本类型只有值,装箱类型除了值之外还有与他们的值不同的同一性(这个估计是说,装箱类型作为对象的不同,尤其在相等比较的时候,下面会有例子)
二、基本类型只有功能完备的值,装箱类型除了对应的基本类型所有值之外还有个非功能值,那就是null,因为它是对象啊
三、基本类型比装箱要节省时间空间
第一个例子:定义这样的一个比较器。
import java.util.Comparator;
public class TestComparator {
static Comparator<Integer> naturalOrder = new Comparator<Integer>() {
@Override
public int compare(Integer first, Integer second) {
return first < second ? -1 : (first == second ? 0 : 1);
}
};
public static void main(String[] args) {
int result = naturalOrder.compare(new Integer(42), new Integer(42));
System.err.println(result);
}
}
这个程序打印出来的结果是1,
(first == second ? 0 : 1 )先在两个对象引用上执行同一性比较,如果first和second引用表示同一个值的不同Integer实例,就返回false
所以记住:
对装箱基本类型运用 == 操作符几乎总是错误的。
对于这个程序的改进就是定义局部变量,先拆箱,也可以避免大量的同一性比较。
第二个例子:
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if(i == 42){
System.out.println("Unbelievable");
}
}
}
这个程序,打印不处理Unbelievable,但是会报空指针一次,因为i没有初始化,默认null,
作者说:当在一项操作中混合使用基本类型和装箱基本类型时,装箱基本类型会自动拆箱。 i==42,会自动拆箱
当对null自动拆箱,就会报空指针异常。
第三个例子:
public static void main(String[] args) {
Long sum = 0L;
long start = System.currentTimeMillis();
for(long i = 0; i < Integer.MAX_VALUE; i++){
sum += i;
}
long end = System.currentTimeMillis();
System.err.println(sum);
System.err.println("用时" + (end - start) + "ms");
long sum2 = 0L;
start = System.currentTimeMillis();
for(long i = 0; i < Integer.MAX_VALUE; i++){
sum2 += i;
}
end = System.currentTimeMillis();
System.err.println(sum2);
System.err.println("用时" + (end - start) + "ms");
}
2305843005992468481
用时18436ms
2305843005992468481
用时4123ms
结果发现,第一个定义sum是装箱类型,用时要多,所以不好,编译器不会报错和警告,但是我们要注意不要这么用。
然后,作者说什么时候必须使用装箱类型呢? 一、作为集合中的元素,键,值 ,要求必须是对象,没有办法,只有有装箱类型
二、参数化,就是泛型的时候也必须是装箱。
总结一下:
自动装箱减少了使用装箱基本类型的繁琐性,但是并没有减少他的风险。
==操作和NullPointerException我们都看到了,还有就是装箱基本类型,导致高开销和不必要的对象创建。