Java Integer 类中 128 陷阱

在 Java 中,基础数据类型与包装类之间的转换是我们经常使用的,但是在一些情况下会出现一些奇怪的事情。看下我们的样例

public class Test {
    public static void main(String[] *args*) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);
        Integer c = 130;
        Integer d = 130;
        System.out.println(c == d);
    }
}

按照代码本身来看,最后两个输出的肯定都是 true。
但是,现实有些时候很真实。
在这里插入图片描述
这是什么?两个人明明都是直接赋值的,怎么就不对了?
这个时候我们就要从底层来检查这里面的猫腻了。
首先,从 main 方法的第一句开始解释。
Integer a = 10;
这句话到底做了几件事?

  1. 编译器首先将基础数据类型的值通过Integer.valueOf()方法封装成包装类的对象。那么,在封装的时候,valueOf()方法到底怎么做的?我们根据源码一点点的进行分析。
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

在这个方法当中,首先先判断里面的数是不是满足 IntegerCache.low 与 IntegerCache.high 当中的数,如果满足的话就直接返回该缓存数组当中的值。否则会返回一个新的 Integer 对象。

而这个 IntegerCache 又是个什么东西,我们再打开 IntegerCache 来一探究竟。

private static class IntegerCache {
    // 这是 IntegerCache 初始化的最小值,注意跟虚拟机当中的属性没有任何关系。
    static final int low = -128;
    // 这是 IntegetCache 初始化的最大值,注意他是跟虚拟机的配置有直接的关系。
    static final int high;
    // 这是用来保存整数缓存池当中的元素
    static final Integer[] cache;
    static {
        // high value may be configured by property
        int h = 127;
        // 获得 JVM 当中设置缓存当中最大的数值。如果没有设置,JVM 默认大小即为 127。设置方式:在 JVM 的 AutoBoxCacheMax=需要设置的缓冲区保存的最大值。
        String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                // 将从虚拟机当中获得的值与默认的最大值进行比较,筛选出里面的最大值
                i = Math.max(i, 127);
                // 取 i 与 Integer.MAX_VALUE - (-low) - 1 之间的最小值。因为这是保证缓存区的数组大小不大于 Integer.Max_Value。
                h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
            } catch (NumberFormatException nfe) {
                // 在 parseInt 方法当中如果转换失败,会捕捉到 NumberFormatException。对这个异常默认没有任何处理。
            }
        }
        high = h;
        // 创建缓存池当中的空间,取决于最大值与最小值之间的空间。*
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // 最后通过断言,检查缓冲区的上界至少是 127。
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

自此,我们可以得到以下结论。在整数的包装类当中,在第一次创建 Integer 类的对象的时候,都会首先创建好缓存数组。当需要包装的值是在 IntegerCache 数组当中的元素的时候,就会返回数组当中的 Integer 对象。JVM 默认就会设置数组的范围为 -128 ~ 127 。除非设置 JVM 当中的 AutoBoxCacheMax 属性大小即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值