Java面试题 — 解释一下Java中的自动装箱和拆箱?

0 阅读4分钟

Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : 解释一下Java中的自动装箱和拆箱?

【简要回答】

  1. 拆装箱介绍 :

    • 装箱 : 基本类型 ——> 包装类型(或者叫对象类型,引用类型)
    • 拆箱 : 包装类型 ——> 基本类型
  2. 手动拆装箱 :

    • JDK5.0之前,拆装箱均是手动完成的
    • 手动装箱,可以使用包装类的构造器来完成,也可以使用 valueOf() 方法。
    • 手动拆箱,以Integer类为例,需要用到 intValue() 方法。
  3. 自动拆装箱 :

    • JDK5.0开始,java提供了自动拆装箱的机制。(不需要手动调用构造器或者方法了)
    • 自动装箱 : 实际上 底层仍然调用了valueOf() 方法。
    • 自动拆箱 : 实际上 底层仍然调用了intValue() 方法(以Integer包装类为例)
  4. 代码演示

    //JDK5.0之前,拆装箱都是手动完成。
        int temp = 19;
    	//手动装箱(基本类型   ————>   包装/引用类型)
        Integer integer_0 = new Integer(temp);      //划线表示该构造方法已过时
        Integer integer_1 = new Integer(11);
        Integer integer_2 = Integer.valueOf(temp);
    	//手动拆箱(包装/引用类型   ————>   基本类型)
        int tempI_0 = integer_0.intValue();     //该方法的接收类型为int类型
    	
    //JDK5.0以后,java提供了自动拆装箱
        Integer integer_3 = 199;    //(自动)装箱——其实底层调用的仍然是valueOf方法(可Debug)
        int tempI_1 = integer_3;    //(自动)拆箱——其实底层调用的仍然是intValue方法
    

【详细回答】

  1. 拆装箱介绍

    • 装箱(Boxing):将基本数据类型转换为对应的包装类型(也称为对象类型或引用类型);eg:将 int 转换为 Integer。
    • 拆箱(Unboxing):将包装类型转换回基本数据类型;eg:将 Integer 转换为 int。
  2. 手动拆装箱

    • 在 JDK 5.0 之前,Java 没有自动拆装箱机制,开发者需要手动完成拆装箱操作
    • 手动装箱:使用包装类的构造器(如 new Integer(10)),但这种方式已过时(Deprecated);更推荐使用包装类的静态方法 valueOf(..)
    • 手动拆箱:使用包装类的实例方法,例如intValue()、doubleValue() 等。
  3. 自动拆装箱

    • 从 JDK 5.0 开始,Java 引入了 自动拆装箱 机制,开发者不需要手动调用方法,编译器会自动完成拆装箱操作
    • 自动装箱:将基本数据类型直接赋值给包装类型时,编译器底层会自动调用 valueOf(..) 方法。
    • 自动拆箱:将包装类型直接赋值给基本数据类型时,编译器底层会自动调用 intValue()、doubleValue() 等方法。
  4. 底层实现

    • 自动装箱底层调用包装类的 valueOf(..) 方法。eg:Integer.valueOf(..) 方法会缓存 -128127 之间的整数,因此在自动装箱时,如果值在这个范围内,会直接从缓存中获取对象,而不会创建新的对象。自动装箱的代码演示如下:

      Integer a = 100;  // 调用 Integer.valueOf(100)
      Integer b = 100;  // 从缓存中获取,a 和 b 是同一个对象 (若 a和b 都是new出来的,那么 a和b 是不同的对象)
      Integer c = 200;  // 超出缓存范围,创建新的对象
      Integer d = 200;  // 创建新的对象,c 和 d 是不同的对象
      
    • 自动拆箱底层调用包装类的 intValue()、doubleValue() 等方法。自动拆箱的代码演示如下:

      Integer integer = 10;
      int num = integer;  // 调用 integer.intValue()
      
  5. 代码演示

    // JDK 5.0 之前,手动拆装箱
    int temp = 19;
    
    // 手动装箱
    Integer integer_0 = new Integer(temp);  // 已过时
    Integer integer_1 = Integer.valueOf(temp);
    
    // 手动拆箱
    int tempI_0 = integer_0.intValue();
    
    // JDK 5.0 之后,自动拆装箱
    Integer integer_3 = 199;  // 自动装箱——底层调用 valueOf(199) 方法
    int tempI_1 = integer_3;  // 自动拆箱——底层调用 intValue() 方法
    

【知识拓展】

  1. Java 中的基本数据类型和对应的包装类型如下

    基本数据类型包装类型
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleDouble
    charCharacter
    booleanBoolean
  2. null值问题:

    • 自动拆箱时,如果包装类型的值为 null,会抛出 NullPointerException。演示代码如下:

      Integer integer = null;
      int num = integer;  // 抛出 NullPointerException
      
  3. 性能问题

    • 频繁的拆装箱操作可能会导致额外的对象创建和内存开销,尤其是在循环中。演示代码如下:

      for (int i = 0; i < 100000; i++) {
      	Integer integer = i;  // 对于 -128 到 127 之间的值,从缓存中获取对象;否则创建新的对象
      }