java基础类型的装箱拆箱

java基础类型的装箱拆箱

通过本文能了解哪些知识?

  • 为什么基本数据类型拆箱有可能会报空指针异常?
  • 基本数据类型的装箱与拆箱操作是如何实现的?

自动拆箱

首先我们有如下代码:

public class Test{
    static {
        Integer integer = new Integer(1234);
        int i = integer;
    }
}

反编译其对应的class文件,得到如下字节码:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return
    LineNumberTable:
      line 1: 0

  static {};
    Code:
       0: new           #2                  // class java/lang/Integer
       3: dup
       4: sipush        1234
       7: invokespecial #3                  // Method java/lang/Integer."":(I)V
      10: astore_0
      11: aload_0
      12: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
      15: istore_1
      16: return
    LineNumberTable:
      line 3: 0
      line 4: 11
      line 5: 16
}

其中int i = integer对应的字节码如下:

11: aload_0
12: invokevirtual #4                  // Method java/lang/Integer.intValue:()I
15: istore_1

可以看出,对于int i = integer,实际上等价于以下语句:

int i = integer.intValue();

那么当integer等于null的时候就变为了((Integer)null).intValue()了,自然就会抛出空指针异常了;对于其他基本数据类型也是同样的原理

自动装箱

首先需要如下代码:

public class Test{
    static {
        int i = 1234;
        Integer integer = i;
    }
}

反编译其对应的class文件,得到如下字节码:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return
    LineNumberTable:
      line 1: 0

  static {};
    Code:
       0: sipush        1234
       3: istore_0
       4: iload_0
       5: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       8: astore_1
       9: return
    LineNumberTable:
      line 3: 0
      line 4: 4
      line 5: 9
}

其中Integer integer = i对应的字节码如下:

4: iload_0
5: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
8: astore_1

也就是对于Integer integer = i语句,实际上等价于:

Integer integer = Integer.valueOf(i);

而因为基本数据类型在java中不存在null值,自然对应的自动装箱操作也就没有自动装箱操作的空指针异常风险了。

结论

最后,我们得到如下结论,对于基本数据类型的自动装箱操作,实际上是使用了Integer.valueOf(int)方法,而对于基本数据类型对应的包装类型的自动拆箱操作,则是使用了Integer#intValue()方法(注意,此方法是普通方法而不是静态方法),所以当对应的Integer对象为null时对其进行自动拆箱操作就会有空指针风险;

关于作者

  • 微信(添加请注明来源):qiao1213812243
  • 微信公众号:java初学者
  • GitHub首页:https://github.com/JoeKerouac

你可能感兴趣的:(J2SE,java,jvm,Java,jvm,J2SE,装箱拆箱)