int与 Integer 之间 == 比较
public static void main(String[] args) {
int basicInt11 = 1;
Integer wrapperInteger11 = 1;
Integer wrapperInteger12 = new Integer(1);
Integer wrapperInteger13 = Integer.valueOf(1);
System.out.println("1[int] == 1[Integer] -> " + (basicInt11 == wrapperInteger11));
System.out.println("1[int] == 1[new Integer(1)] -> " + (basicInt11 == wrapperInteger12));
System.out.println("1[int] == 1[Integer.valueOf(1)] -> " + (basicInt11 == wrapperInteger13));
System.out.println("1[Integer] == 1[new Integer(1)] -> " + (wrapperInteger11 == wrapperInteger12));
System.out.println("1[Integer] == 1[Integer.valueOf(1)] -> " + (wrapperInteger11 == wrapperInteger13));
System.out.println("====================================");
int basicInt21 = 128;
Integer wrapperInteger21 = 128;
Integer wrapperInteger22 = new Integer(128);
Integer wrapperInteger23 = Integer.valueOf(128);
System.out.println("128[int] == 128[Integer] -> " + (basicInt21 == wrapperInteger21));
System.out.println("128[int] == 128[new Integer(1)] -> " + (basicInt21 == wrapperInteger22));
System.out.println("128[int] == 128[Integer.valueOf(1)] -> " + (basicInt21 == wrapperInteger23));
System.out.println("128[Integer] == 128[new Integer(1)] -> " + (wrapperInteger21 == wrapperInteger22));
System.out.println("128[Integer] == 128[Integer.valueOf(1)] -> " + (wrapperInteger21 == wrapperInteger23));
}
结果
1[int] == 1[Integer] -> true
1[int] == 1[new Integer(1)] -> true
1[int] == 1[Integer.valueOf(1)] -> true
1[Integer] == 1[new Integer(1)] -> false
1[Integer] == 1[Integer.valueOf(1)] -> true
====================================
128[int] == 128[Integer] -> true
128[int] == 128[new Integer(1)] -> true
128[int] == 128[Integer.valueOf(1)] -> true
128[Integer] == 128[new Integer(1)] -> false
128[Integer] == 128[Integer.valueOf(1)] -> false
从以上可看出,基本类型与包装类型 == 比较始终相对。
而包装类型,值一样,采取初始化方式不一样, ==结果不一样。
1[Integer] == 1[new Integer(1)] -> false
1[Integer] == 1[Integer.valueOf(1)] -> true
值为 128的时候, 128[Integer] == 128[Integer.valueOf(1)] -> false 结果也不一样。
分析,java 的数据分为基本类型和引用类型。 == 进行比较。则基本类型比较的是值, 引用类型则比较的是引用地址。
同一个class的不同对象(new 出来的) 必然引用地址不想等。
查看 Integer 源码:
public Integer(int value) {
this.value = value;
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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() {}
}
从源码可看出, new Integer(1) 与 Integer.valueOf(1) 初始化是不一样的。
new Integer(1) 是完全新建一个对象。
Integer.valueOf(1) 则会先查找本地缓存是否存在该对象,存在则直接返回,不存在,则新建一个对象。
而 Intger aa = 1 , 这种格式,JVM是怎么初始化的呢? 这其实需要把 .java文件,先转成 .class文件,然后再反编译.class文件看,即可明白。
设上面为 A.java 则windows下面, 在此文件目录 shift +右键 选择:在此处打开命令, 输入 javac A.java
则通过 Java Decompiler 打开 A.class
public static void main(String[] paramArrayOfString)
{
int i = 1;
Integer localInteger1 = Integer.valueOf(1);
Integer localInteger2 = new Integer(1);
Integer localInteger3 = Integer.valueOf(1);
System.out.println(new StringBuilder().append("1[int] == 1[Integer] -> ").append(i == localInteger1.intValue()).toString());
System.out.println(new StringBuilder().append("1[int] == 1[new Integer(1)] -> ").append(i == localInteger2.intValue()).toString());
System.out.println(new StringBuilder().append("1[int] == 1[Integer.valueOf(1)] -> ").append(i == localInteger3.intValue()).toString());
System.out.println(new StringBuilder().append("1[Integer] == 1[new Integer(1)] -> ").append(localInteger1 == localInteger2).toString());
System.out.println(new StringBuilder().append("1[Integer] == 1[Integer.valueOf(1)] -> ").append(localInteger1 == localInteger3).toString());
System.out.println("====================================");
int j = 128;
Integer localInteger4 = Integer.valueOf(128);
Integer localInteger5 = new Integer(128);
Integer localInteger6 = Integer.valueOf(128);
System.out.println(new StringBuilder().append("128[int] == 128[Integer] -> ").append(j == localInteger4.intValue()).toString());
System.out.println(new StringBuilder().append("128[int] == 128[new Integer(1)] -> ").append(j == localInteger5.intValue()).toString());
System.out.println(new StringBuilder().append("128[int] == 128[Integer.valueOf(1)] -> ").append(j == localInteger6.intValue()).toString());
System.out.println(new StringBuilder().append("128[Integer] == 128[new Integer(1)] -> ").append(localInteger4 == localInteger5).toString());
System.out.println(new StringBuilder().append("128[Integer] == 128[Integer.valueOf(1)] -> ").append(localInteger4 == localInteger6).toString());
}
从上可看出 javac 后的二进制代码与写的有些不一样。 这是因为,编译器对此进行了优化(可能不同版本编译器,上面结果还有些不一样)。
Integer a = 1; 其实编译后,JVM看到的是 Integer a = Integer.valueOf(1);
基本类型和包装类型比较时, int b=1 ; Intger a=1; == 两边,只要有基本类型, 则另外一边返回的也一定是基本类型 (localInteger5.intValue())。
因此是基本类型的值比较。
public int intValue() {
return value;
}
总结: 用 == 的时候 一定要保证是基本类型的比较,而不是引用类型的比较。当存在包装类型的时候, 最好转化为 基本类型,再用 ==,防止出现 ==两边都是包装类型。