【Java】自动装箱(boxing)和拆箱

262 阅读2分钟

1.1 基本类型和包装类型

基本类型包装类型
booleanBoolean
byteByte
charCharacter
intInteger
shortShort
longLong
floatFloat
doubleDouble

除了char和int,其他包装类型写法为基本类型的首字母大写。

1.1.1 基本类型和包装类型的区别
  1. 从内存上:基本类型存在栈里,包装类型为对象存在堆里。
  2. 从内容上:包装类型是对基本类型的包装,符合POJO规范,基本类型作为自己的成员变量和有set,get方法。
  3. 从使用上:包装类型可用于泛型,基本类型不可以。
  4. 从效率上:基本类型更易用,快速。
1.1.2 自动装箱和拆箱

定义:把基本类型转换成包装类型叫装箱(boxing),反之,叫拆箱。 原理:自动装箱通过包装类型的valueOf()方法,拆箱通过包装类型的xxxValue()方法。

1.1.3 自动装箱和拆箱的坑
// 1)基本类型和包装类型
int a = 100;
Integer b = 100;
System.out.println(a == b); # true

// 2)两个包装类型
Integer c = 100;
Integer d = 100;
System.out.println(c == d); # true

// 3)
c = 200;
d = 200;
System.out.println(c == d); # false

上述代码,要知道==对基本类型比较值,对引用类型(对象)比较对象地址。

  1. 当基本类型和包装类型比较时,包装类型自动拆箱成基本类型然后比较。
  2. 对于-128~127之间的数,Jvm通过优化直接从缓冲池返回此对象。详见后面讲解。
  3. 对于不在-128~127之间的数,重新创建包装类对象放入堆内存。
1.1.4 包装类对象的缓冲池

上述代码2)就是针对-128~127之间的Integer包装类对象直接从缓冲池内返回。

 /**
  * 首先会判断i是否在[IntegerCache.low,Integer.high]之间
  * 如果是,直接返回Integer.cache中相应的元素
  * 否则,调用构造方法,创建一个新的Integer对象
  */
 public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
 }

总结:

  • Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。即对于-128~127之间的值,直接从缓冲池内返回。对于Character范围为0~127。
  • Double、Float的valueOf方法的实现是类似的。即直接创建返回新包装类对象。

传包装类型的坑 当将一个Integer的包装类型当作参数传递给函数时,在函数中修改这个Integer并不会影响原来的包装类型。 image.png

可以看到包装类型的value是被final修饰的,在函数中修改包装类型的值其实是新建了一个包装类对象。 image.png image.png