自动拆装箱

基本数据类型

基本数据类型的好处

  • 在Java语言中,new一个对象是存储在堆里的,我们通过栈中的引用来使用这些对象;所以,对象本身来说是比较消耗资源的。
  • 基本数据类型不使用new创建,不存储在堆里,而是直接在栈中存储,因此会更加高效。

包装类

基本数据类型 包装类
char Character
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double

自动装箱与自动拆箱

  • 基本数据类型转换成包装类的过程就是打包装,英文是boxing,翻译为装箱。
  • 包装类转换成基本数据类型的过程就是拆包装,英文是unboxing,翻译为拆箱。

自动装箱与自动拆箱的实现原理

自动拆装箱的代码:

public void testBoxing() {
    Character charObj = 'a';
    char charVal = charObj;
    Boolean booleanObj = true;
    boolean booleanVal = booleanObj;
    Byte byteObj = 1;
    byte byteVal = byteObj;
    Short shortObj = 1;
    short shortVal = shortObj;
    Integer intObj = 1;
    int intVal = intObj;
    Long longObj = 1l;
    long longVal = longObj;
    Float floatObj = 1f;
    float floatVal = floatObj;
    Double doubleObj = 1d;
    double doubleVal = doubleObj;
}

反编译后得到:

public void testBoxing() {
    Character character = Character.valueOf('a');
    char c = character.charValue();
    Boolean bool = Boolean.valueOf(true);
    boolean bool1 = bool.booleanValue();
    Byte byte_ = Byte.valueOf((byte)1);
    byte b = byte_.byteValue();
    Short short_ = Short.valueOf((short)1);
    short s = short_.shortValue();
    Integer integer = Integer.valueOf(1);
    int i = integer.intValue();
    Long long_ = Long.valueOf(1L);
    long l = long_.longValue();
    Float float_ = Float.valueOf(1.0F);
    float f = float_.floatValue();
    Double double_ = Double.valueOf(1.0D);
    double d = double_.doubleValue();
}

可以看出,自动装箱都是通过包装类的valueOf()方法来实现的,自动拆箱都是通过包装类对象的xxxValue()来实现的。

自动装箱拆箱容易混淆的场景

场景一,包装类型和基本类型的比较,包装类型进行自动拆箱。

    Integer a = 300;
    System.out.println(a == 1 ? "等于" : "不等于");
    Boolean bool = false;
    System.out.println(bool ? "真" : "假");

反编译后:

    Integer a = Integer.valueOf(300);
    System.out.println((a.intValue() == 1) ? ": ");
    Boolean bool = Boolean.valueOf(false);
    System.out.println(bool.booleanValue() ? ": ");

场景二,包装类型的计算,包装类型自动拆箱。

    Integer i = 10;
    Integer j = 20;
    System.out.println(i + j);

反编译后:

    Integer i = Integer.valueOf(10);
    Integer j = Integer.valueOf(20);
    System.out.println(i.intValue() + j.intValue());

场景三,三目运算符,混合基本类型时,包装类型自动拆箱;若接收值是包装类型,则结果自动装箱。

    boolean b = true;
    int k1 = b ? i : j;
    int k2 = b ? i : 20;
    Integer k3 = b ? i : j;
    Integer k4 = b ? i : 20;

反编译后:

    boolean b = true;
    int k1 = (b ? i : j).intValue();
    int k2 = b ? i.intValue() : 20;
    Integer k3 = b ? i : j;
    Integer k4 = Integer.valueOf(b ? i.intValue() : 20);

自动拆装箱与缓存

在Boxing Conversion部分的Java语言规范(JLS)规定如下:
如果一个变量p的值是:

  • -128至127之间的整数(§3.10.1)
  • true 和 false的布尔值 (§3.10.3)
  • ‘\u0000’至 ‘\u007f’之间的字符(§3.10.4)

范围内的时,将p包装成a和b两个对象时,可以直接使用a==b判断a和b的值是否相等。
注意:这里的整数不只针对Integer,也包括Byte、Short、Long以及BigDecimal等。

自动拆装箱带来的问题

  • 包装对象的数值比较,不能简单的使用==,虽然-128到127之间的数字可以,但是这个范围之外还是需要使用equals比较。
  • 在自动拆箱时,如果包装类对象为null,会抛出NPE。
  • 如果一个for循环中有大量拆装箱操作,会浪费很多资源。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。