一. 自动装箱和拆箱的概念

自动装箱和拆箱主要指的java基本类型和对应的包装类之间的隐式转换。自动装箱就是将基本数据类型自动转化成对应的包装类,拆箱是把包装类自动转换成对应基本数据类型。java基本类型和对应的包装类如下:

Java 自动装箱与拆箱原理 java什么是自动拆装箱_自动装箱

二.自动装箱和拆箱的实现

  • 代码示例
public class PrimitiveTypeWrapperTest {
    public static void main(String[] args) {
        //自动装箱
        Integer i=6;
        //自动拆箱
        int a=i;
        System.out.println("i:"+i);
        System.out.println("a:"+a);
    }
}
  • 反编译class文件解析分析
L0
    LINENUMBER 14 L0
    BIPUSH 6
    INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
    ASTORE 1
   L1
    LINENUMBER 16 L1
    ALOAD 1
    INVOKEVIRTUAL java/lang/Integer.intValue()I
    ISTORE 2

在装箱的过程中,实际上是调用Integer包装类的valueOf()静态方法,而在装箱的过程中,实际上是调用Integer包装类intVaue()方法。

  • Integer包装类valuesOf()和intValue()源码解析
public static Integer valueOf(int i) {
        //1.判断int值是否在缓存里,如果存在从缓存取出,否则创建一个新的Integer对象
        //2.IntegerCache存储的值范围在-128~127
            if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
private final int value;
public int intValue() {
    return value;
}
  • Integer自动装箱题目示例
public class PrimitiveTypeWrapperTest {
    public static void main(String[] args) {
        Integer a=128;
        Integer b=128;

        Integer c=127;
        Integer d=127;

        System.out.println(a==b);//false
        System.out.println(c==d);//true
    }
}

==比较的是两个引用变量是否指向同一个对象,也就是指向对象的地址是否相同。a和b指向的对象在类初在加载的时候就已经初始化完毕,指向的是同一个对象。c和d因为不在缓存范围之内,每次都是重新初始化一个新的对象,在堆内存分配一个新的内存空间,指向的是新的对象,所以是false

思考:自动装箱除了Integer这样实现之外,其他包装类是否都是这样实现?

  • 题目分析
public class PrimitiveTypeWrapperTest {
    public static void main(String[] args) {
        Float a=127.0f;
        Float b=127.0f;

        Double c=127.0;
        Double d=127.0;

        System.out.println(a==b);//false
        System.out.println(c==d);//false

    }
}
  • Double和Float包装类valuesOf源码分析
//Double和Float做类型转换的时候都是直接初始化一个新对象
public static Double valueOf(double d) {
      return new Double(d);
}
public static Float valueOf(float f) {
    return new Float(f);
}

思考:Integer i=1;i+=1;做了什么事情?

  • Integer i=1 自动装箱,调用valueOf方法
  • i+1对象和基本类型运算,调用intValue方法将i转换成ini类型,运算结果是int类型
  • 将i+1运算结果调用valueOf方法转换成Integer类型

思考:关于包装类equals()方法分析

  • 代码示例
public class PrimitiveTypeWrapperTest {
    public static void main(String[] args) {
        Integer a=128;
        Integer b=128;
        System.out.println(a==b);//false
        System.out.println(a.equals(b));//true

    }
}
  • equals()方法源码分析
//Object对象equals方法,比较的是否是同一个对象
public boolean equals(Ob,ject obj) {
     return (this == obj);
 }
//Integer包装类重写了equals方法,比较的是对象的值
public boolean equals(Object obj) {
      if (obj instanceof Integer) {
          return value == ((Integer)obj).intValue();
      }
      return false;
 }

对于所有的包装类都重写了equals方法,比较的都是对象的值