《深入理解Java虚拟机》Java语法糖 -自动装拆箱与泛型

文章详细分析了Java中的自动拆装箱过程,通过字节码展示了如何通过Integer.valueOf和intValue方法实现装箱和拆箱。同时,解释了Java泛型在编译后的类型擦除现象,尽管在源代码中使用了泛型如ArrayList<Integer>,但在字节码中实际操作的对象是Object类型。这种设计使得Java能够在运行时保持向后兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《深入理解Java虚拟机》Java语法糖

1.自动拆装箱

如下的代码

 public static void main(String[] args) {

        ArrayList<Integer> its = new ArrayList<>();

        its.add(0);

        int result = its.get(0);

        System.out.println("result = " + result);
    }

对应的字节码

 0 new #2 <java/util/ArrayList>
 3 dup
 4 invokespecial #3 <java/util/ArrayList.<init> : ()V>
 7 astore_1
 8 aload_1
 9 iconst_0
10 invokestatic #4 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
13 invokevirtual #5 <java/util/ArrayList.add : (Ljava/lang/Object;)Z>
16 pop
17 aload_1
18 iconst_0
19 invokevirtual #6 <java/util/ArrayList.get : (I)Ljava/lang/Object;>
22 checkcast #7 <java/lang/Integer>
25 invokevirtual #8 <java/lang/Integer.intValue : ()I>
28 istore_2
29 getstatic #9 <java/lang/System.out : Ljava/io/PrintStream;>
32 new #10 <java/lang/StringBuilder>
35 dup
36 invokespecial #11 <java/lang/StringBuilder.<init> : ()V>
39 ldc #12 <result = >
41 invokevirtual #13 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
44 iload_2
45 invokevirtual #14 <java/lang/StringBuilder.append : (I)Ljava/lang/StringBuilder;>
48 invokevirtual #15 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
51 invokevirtual #16 <java/io/PrintStream.println : (Ljava/lang/String;)V>
54 return

可以看偏移量10 和 偏移量25的指令 ,通过调用对应包装类的ValueOf方法完成装箱,调用intValue方法完成拆箱

invokestatic #4 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>

25 invokevirtual #8 <java/lang/Integer.intValue : ()I>

2. 泛型与类型擦除

 0 new #2 <java/util/ArrayList>
 3 dup
 4 invokespecial #3 <java/util/ArrayList.<init> : ()V>
 7 astore_1
 8 aload_1
 9 iconst_0
10 invokestatic #4 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
13 invokevirtual #5 <java/util/ArrayList.add : (Ljava/lang/Object;)Z>
16 pop
17 aload_1
18 iconst_0
19 invokevirtual #6 <java/util/ArrayList.get : (I)Ljava/lang/Object;>
22 checkcast #7 <java/lang/Integer>
25 invokevirtual #8 <java/lang/Integer.intValue : ()I>
28 istore_2
29 getstatic #9 <java/lang/System.out : Ljava/io/PrintStream;>
32 new #10 <java/lang/StringBuilder>
35 dup
36 invokespecial #11 <java/lang/StringBuilder.<init> : ()V>
39 ldc #12 <result = >
41 invokevirtual #13 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
44 iload_2
45 invokevirtual #14 <java/lang/StringBuilder.append : (I)Ljava/lang/StringBuilder;>
48 invokevirtual #15 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
51 invokevirtual #16 <java/io/PrintStream.println : (Ljava/lang/String;)V>
54 return

我们创建的集合指定的泛型为Integer,而查看字节码信息,发现却变成了Object

13 invokevirtual #5 <java/util/ArrayList.add : (Ljava/lang/Object;)Z>
19 invokevirtual #6 <java/util/ArrayList.get : (I)Ljava/lang/Object;>

这是因为对JVM来说,不存在泛型。Java编译器会将泛型转化为当前泛型所能指代的类中的最高父类。

如果有声明继承的类的泛型,将转换为声明父类的类型

  public static void main(String[] args) {

        ArrayList<Dog> its = new ArrayList<>();

        Dog e = new Example().new Dog();
        its.add(e);

    }


    class Dog {

    }
 0 new #2 <java/util/ArrayList>
 3 dup
 4 invokespecial #3 <java/util/ArrayList.<init> : ()V>
 7 astore_1
 8 new #4 <Example$Dog>
11 dup  public static void main(String[] args) {

        ArrayList<Dog> its = new ArrayList<>();

        Dog e = new Example().new Dog();
        its.add(e);

    }


    class Dog extends Animal{

    }
12 new #5 <Example>
15 dup
16 invokespecial #6 <Example.<init> : ()V>
19 dup
20 invokevirtual #7 <java/lang/Object.getClass : ()Ljava/lang/Class;>
23 pop
24 invokespecial #8 <Example$Dog.<init> : (LExample;)V>
27 astore_2
28 aload_1
29 aload_2
30 invokevirtual #9 <java/util/ArrayList.add : (Ljava/lang/Object;)Z>
33 pop
34 return

  public static void main(String[] args) {

        ArrayList<Dog> its = new ArrayList<>();

        Dog e = new Example().new Dog();
        its.add(e);

    }


    class Dog extends Animal{

    }
    
    class Animal{

    }
 0 aload_0
 1 aload_1
 2 putfield #1 <Example$Dog.this$0 : LExample;>
 5 aload_0
 6 aload_1
 7 invokespecial #2 <Example$Animal.<init> : (LExample;)V>
10 return

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋日的晚霞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值