在Java中,我们经常使用Integer类来处理整数。然而,这个看似简单的类实际上隐藏着一个被称为“128陷阱”的安全漏洞。这个陷阱可能会导致一些意想不到的结果和安全问题。
首先,让我们来看一个例子:
Integer a = 100;
Integer b = 100;
System.out.println(a==b);
在这个例子中,我们创建了两个Integer对象a和b,它们都引用了相同的整数值100。然后,我们将a赋值给了一个int类型的变量e,将b的intValue()方法返回的值赋值给了另一个int类型的变量f。最后,我们比较了a和b是否相等。
输出结果是true
,这是因为在Java中,对象的比较是基于它们的引用,而不是它们的值。所以,尽管a和b的值相同,但它们是不同的对象,因此它们是不相等的。
接下来,让我们看另一个例子:
Integer c = 1000;
Integer d = 1000;
System.out.println(c==d);
在这个例子中,我们创建了两个Integer对象c和d,它们都引用了相同的整数值1000。然后,我们比较了c和d是否相等。
输出结果是false
,这是因为在Java中,对象的比较是基于它们的值,而不是它们的引用。所以,尽管c和d的值相同,但它们是不同的对象,因此它们是不相等的。
这就是所谓的“128陷阱”。当我们使用Integer类时,我们需要特别注意这个问题。如果我们需要比较两个Integer对象的值是否相等,我们应该使用equals()
方法,而不是==
操作符。例如:
Integer a = 100;
Integer b = 100;
System.out.println(a.equals(b)); // 输出结果是true
总之,Java中的Integer类型有一个名为“128陷阱”的安全漏洞。为了避免这个问题,我们应该始终使用equals()
方法来比较两个Integer对象的值是否相等,而不是使用==
操作符。
而具体是为什么呢?请往下继续看
Integer的valueOf源码:
这个方法的意思是:
将一个基本数据类型int
转换为Integer
对象。方法名为valueOf
,接受一个整数参数i
。
首先,代码检查i
是否在IntegerCache.low
和IntegerCache.high
之间(包括边界值)。IntegerCache
是一个内部类,用于缓存一定范围内的整数值,以提高性能。如果i
在这个范围内,那么直接从缓存中返回对应的Integer
对象。
如果i
不在缓存范围内,那么创建一个新的Integer
对象,并将i
作为参数传递给它的构造函数。最后,返回这个新创建的Integer
对象。
IntegerCache源码:
这个方法大概意思是:
IntegerCache
的私有静态类,用于缓存一定范围内的整数值。这个类有三个静态成员变量:low
表示缓存范围的下限,high
表示缓存范围的上限,cache
是一个数组,用于存储缓存的整数值。
在类的静态初始化块中,首先设置high
的默认值为127。然后尝试从系统属性中获取名为java.lang.Integer.IntegerCache.high
的属性值,并将其解析为整数。如果解析成功,将h
设置为解析得到的整数值和127中的较大者;如果解析失败,忽略该属性值。接下来,将h
设置为h
和Integer.MAX_VALUE - (-low) - 1
中的较小者,以确保数组大小不超过Integer.MAX_VALUE
。最后,将high
的值设置为h
。
接着,根据high
和low
之间的差值创建一个Integer
类型的数组cache
,并使用循环将范围内的整数值依次存储到数组中。注意,范围[-128, 127]必须被内部化(JLS7 5.1.7)。
此外,还定义了一个私有构造函数,以防止外部实例化这个类。
所以最后当赋值超过[-128, 127]这个范围的数,它就会创建两个对象,两个对象虽然数值相等,但它们的对象是不同的,导致使用“==”时是false。