JAVA 源码分析Integer的128陷阱

文章介绍了Java中Integer包装类的128陷阱现象,当数值在-128到127之间时,它们会被共享一个对象,导致相等判断为真;超出此范围则会创建新对象,相等判断为假。文章详细剖析了valueOf方法和IntegerCache的缓存机制。
摘要由CSDN通过智能技术生成

128陷阱介绍及演示

首先什么是128陷阱?

Integer包装类两个值大小在-128到127之间时可以判断两个数相等,因为两个会公用同一个对象,返回true,
但是超过这个范围两个数就会不等,因为会变成两个对象,返回false。

举个例子:
现有以下程序

    public static void main(String[] args) {
        Integer a = 125;
        Integer b = 125;
        Integer c = 129;
        Integer d = 129;
        System.out.println(a==b);
        System.out.println(c==d);
    }

结果输出如下:
在这里插入图片描述

前两个在范围内的变量在判断相等为真,后两个在判断相等时为假。

源码分析

我们创建变量时使用的代码
Integer a = 125;
在编译后其实会转变为
Integer a = Integer.valueOf(125);
因此我们在设置变量时执行的其实是Interger类的valueOf方法。
那么我们在源码中查看该方法

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

可以发现这个方法中调用了静态类IntegerCache中的属性,这个类实际上用来进行缓存的,那么我们再来查看这个静态类。

 private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // high value may be configured by property
            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;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

可以看到这个类中的low值为-128,high的值为127,但我们每次使用这个类时,都会执行类中静态代码块,也就是static中的一堆代码。那么这些代码的作用是什么呢?
该静态代码块主要用于初始化一个缓存数组,其中缓存了范围在 -128 到 127 之间的整数对象,以提高性能和节省内存。

因此在valueOf方法中当传递来的参数在-128到127之间时就会直接引用缓存数组中的整数值,不在这个范围则会创建新的对象,所以就造成128陷阱,因为在这个范围内数引用的都是同一个对象,所以=会判定其相等,超出这个范围创建新的对象表示,=当然就不会判定这两个新对象相等。

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 自动装箱(Autoboxing)是 Java 1.5 版本之后引入的新特性,可以将基本类型自动转换为对应的包装类型,反之也可以。具体来说,就是在需要使用包装类型的地方,可以直接使用基本类型,而 Java 编译器会自动将其转换为对应的包装类型。 Java 自动装箱的实现是通过编译器在编译期间自动插入装箱(Boxing)和拆箱(Unboxing)的代码来完成的。具体来说,当编译器发现一个需要使用包装类型的地方,它会自动插入一个将基本类型转换为包装类型的代码,而当编译器发现一个需要使用基本类型的地方,它会自动插入一个将包装类型转换为基本类型的代码。 下面简单介绍一下自动装箱的源码实现: 1. 自动装箱 自动装箱是通过调用对应包装类型的 valueOf 方法来实现的。例如,当需要将 int 类型的变量 i 转换为 Integer 类型时,编译器会自动插入如下代码: ```java Integer i = Integer.valueOf(i); ``` 其中,valueOf 方法定义在对应包装类型的类中,例如 Integer 类中的 valueOf 方法如下: ```java public static Integer valueOf(int i) { return new Integer(i); } ``` 2. 自动拆箱 自动拆箱是通过调用对应包装类型的 xxxValue 方法来实现的。例如,当需要将 Integer 类型的变量 i 转换为 int 类型时,编译器会自动插入如下代码: ```java int i = i.intValue(); ``` 其中,xxxValue 方法定义在对应包装类型的类中,例如 Integer 类中的 intValue 方法如下: ```java public int intValue() { return value; } ``` 以上是 Java 自动装箱的源码分析,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值