java Integer(-128~127)使用==和equals比较产生的思考

最近同事问我,为什么Integer(127)会等于Integer(127)。下面我们先做个试验:

示例1:

1
2
3
4
5
6
7
8
9
10
11
12
Integer a = 127;
Integer b = 127;
System.out.println(a==b);
//true
Integer c = 128;
Integer d = 128;
System.out.println(c==d);
//false
Integer e = new Integer(1);
Integer f = new Integer(1);
System.out.println(e==f);
//false

为什么到128就不行了呢?

我们看下JDK源码,发现有个IntegerCache的东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
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() {}
}

里面有个静态代码块,会吧-128~127放到cache[]中.当我们使用valueOf方法的时候,会从cache中取出相同的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

也就是说,当我们用valueOf方法创建Integer的时候。如果值相同,就会指向缓存中的同一个对象。所以==的时候会是true。

而且注释说了,推荐我们优先用valueOf而不是new Integer().

下面我们测试一下

示例2:

1
2
3
4
5
6
7
8
Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
System.out.println(a==b);
//true
Integer c = new Integer(127);
Integer d = new Integer(127);
System.out.println(c==d);
//false

当我们用new Integer()的时候,创建的是一个新的对象,所以==返回false.

另外,里面还有一个java的语法糖。java编译器会对Integer a = 127自动装箱。变成Integer a = Integer.valueOf(127),所示例1中的ab是相等的。


java Integer(-128~127)使用==和equals比较产生的思考
https://www.wekri.com/java/java-integer-equals/
Author
Echo
Posted on
March 8, 2019
Licensed under