深入理解jvm-泛型擦除与语法糖(拆箱装箱)

本文为读书笔记

1. 泛型擦除

擦除式泛型的实现几乎只需要在Javac编译器上做出改进即可,不需要改动字节码、不需要改动Java虚拟机,也保证了以前没有使用泛型的库可以直接运行在Java 5.0之上。

泛型擦除的实现:

擦除前:
在这里插入图片描述

擦除后:
在这里插入图片描述

可见:
java的类型擦除是把T 在编译时直接抹去,编程类似于ArrayList list 这样的裸类型;而在调用的时候进行强制类型转换;

但是问题出现了:
在这里插入图片描述
这样的代码目前java是不支持的,想要用基本类型的集合类,得用包装类,那么问题就出现,每次调用集合类都要进行一次拆箱装箱,这无疑是对性能的一种开销;

2. 自动拆箱装箱

装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
在这里插入图片描述
在这里插入图片描述
以及:
在这里插入图片描述
第一个true:
反编译一下看调用了什么:
在这里插入图片描述
执行了 Integer.valueof这个static方法
在这里插入图片描述

 private static class IntegerCache {
        static final int low = -128;
        static final int high;
          static {
        int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
          }
          一般情况下是127

所以可见,返回的是缓存池里池内同一个对象

超过范围:-128-127 之后就不会从缓存池里取了;

故第二个 false 也能解释了;

第三四个true:
在这里插入图片描述
调用的是Integer.intValue来获取值,最后判等就行了故为true

**注意 == 是值相等 **

再来看g 由于 拆箱装箱,所以 左边是一个long的 3 == 右边 int 3
相等

最后一个:
在这里插入图片描述
调用的是long的equals

  public boolean equals(Object obj) {
        if (obj instanceof Long) {
            return value == ((Long)obj).longValue();
        }
        return false;
    }

很明显不是 Long类型,故false

由此可以得出结论:

数值类型包装类 装箱(设置值) valueof() 拆箱(获取值) xxxValue()

== 值相等的前提是 左右触发了拆箱 ==做值相等,而不是地址相等
在这里插入图片描述
在这里插入图片描述
equals为重写方法,调用相关基本类型的包装类方法:
首先判断实例类型,再判断值

发布了37 篇原创文章 · 获赞 6 · 访问量 4639

猜你喜欢

转载自blog.csdn.net/littlewhitevg/article/details/105562495