六、Java中的自动装箱和拆箱

180 阅读1分钟

装箱: 自动将基本数据类型转换为包装器类型 拆箱: 自动将包装器类型转换为基本数据类型

在JavaSE5之前,如果要生成一个数值为10的Integer对象,必须要这样写

Integer i = new Integer(10);

JavaSE5之后开始就提供了自动装箱的特性,只需要酱紫就可以了

Integer i=10;

所有的包装类型都是不变类,一旦创建,就是不变的

// Integer源码
public final class Integer {
    private final int value;
}
基本类型引用类型
booleanjava.lang.Boolean
bytejava.lang.Byte
shortjava.lang.Short
intjava.lang.Integer
longjava.lang.Long
floatjava.lang.Float
doublejava.lang.Double
charjava.lang.Character

面试题:

public class Test{
    public static void main(String[] args){
        Integer a1=100;
        Integer a2=100;
        Integer a3=200;
        Integer a4=200;
       System.out.println(a1==a2) //true
       System.out.println(a3==a4) //false
       System.out.println(a3.equals(a4)); // true
    }
}

为什么会出现这样的结果呢?输出的结果a1和a2指向的是同一个对象,而a3和a4指向的是不同的对象,看一下源码:

public static Integer valueOf(int i) {
    //如果i的值大于-128小于127则返回一个缓冲区(常量池)中的已经初始化后Integer对象
    if (i >= IntegerCache.low && i <= IntegerCache.high)
         return IntegerCache.cache[i + (-IntegerCache.low)];
    }else{
         return new Integer(i);
    }
}

可以看出,在通过ValueOf()方法创建Integer对象的时候,如果数值在[-128,127]之间,返回指向IntegerCache.cache中已经存在的对象的引用,否则它就会创建一个新的Integer对象,上边代码中的a3和a4分别指向了两个不同的对象,所以不相等;

📝注意: 包装类必须使用equals去比较。== 操作比较的是两个变量的值,对于引用型变量是判断变量是否指向同一引用对象,比地址。equals 操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

总结

  • 自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5);
  • 装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException;
  • 包装类型的比较必须使用equals();
  • 整数和浮点数的包装类型都继承自Number;