这个是比较基础的问题,也是常见的问题,也是经常会被问到的问题,那么,我们研究下为什么?
直接看代码
public class IntegerTest {public static void main(String[] args) {Integer a = 128;Integer b = 128;int c = 128;// falseSystem.out.println(a == b);//trueSystem.out.println(a == c);//trueSystem.out.println(a.equals(b));}
}
false
true
true
public class IntegerTest {public static void main(String[] args) {Integer a = 127;Integer b = 127;int c = 127;System.out.println(a == b);System.out.println(a == c);System.out.println(a.equals(b));}
}
//结果
true
true
true
现象:
a = 128,b=128时不相等
a = 127,b=127时相等
a==c时,相等
a.equals(b)时,相等
为什么?
IntegerCache,jvm启动后会加载此静态类,值的范围为-128~127
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 propertyint h = 127;String integerCacheHighPropValue =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_VALUEh = 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() {}}
IntegerCache 注意看 是一个静态内部类, 它的常量low=-128 下面还有一个static静态块, h赋值是127
当jvm启动时静态类和静态块会优先加载,会把这些数值存在 命名为cache[] 数组中,加载到了常量池中
IntegerCache.low 初始化值是-128
IntegerCache.high初始化值是 127
那么当我赋值 Integer a=128 的时候, a大于-128 但是不小于127 , 所以走 new Integer, 是个新对象
我再赋值一个 Integer b=128 进来也是这样的流程,也会new Integer 这时用== 他们两个对象地址都是new的 是个全新的, 所以是不相等。
所以Integer c=127 和Integer d=127 取得都是同一个对象的地址。因为127存在常量池中
使用System.identityHashCode() 这个方法会输出改对象的地址
我们在看看equals方法
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;}
转成数据类型了,而非引用类型