作为Java初学者,int与Integer的比较之前一直有地方不清楚,花了点时间研究一下,现在基本明白了,记录如下,以备查阅。
示例
int A1 = 127;
int A2 = 127;
System.out.println("int与int比较127:A1==A2 "+ (A1==A2));
System.out.println("**************************************");
int B1 = 127;
Integer B2 = 127;
System.out.println("int与Integer比较127:B1==B2 "+ (B1==B2));
System.out.println("int与Integer比较127:B2.equals(B1) "+ (B2.equals(B1)));
System.out.println("**************************************");
Integer C1 = 127;
Integer C2 = 127;
System.out.println("Integer与Integer比较127:C1==C2 "+ (C1==C2));
Integer C3 = 128;
Integer C4 = 128;
System.out.println("Integer与Integer比较128:C3==C4 "+ (C3==C4));
System.out.println("**************************************");
Integer E1 = Integer.valueOf(127);
Integer E2 = Integer.valueOf(127);
System.out.println("Integer与Integer比较127:E1==E2 "+ (E1==E2));
Integer E3 = Integer.valueOf(128);
Integer E4 = Integer.valueOf(128);
System.out.println("Integer与Integer比较128:E3==E4 "+ (E3==E4));
System.out.println("**************************************");
//public Integer(int value)已不建议使用
//使用静态方法public static Integer valueOf(int i),空间与时间的性能更好
Integer D1 = new Integer(127);
Integer D2 = new Integer(127);
System.out.println("Integer与Integer比较127:D1==D2 "+ (D1==D2));
Integer D3 = new Integer(128);
Integer D4 = new Integer(128);
System.out.println("Integer与Integer比较128:D3==D4 "+ (D3==D4));
System.out.println("**************************************");
答案
int与int比较127:A1==A2 true
**************************************
int与Integer比较127:B1==B2 true
int与Integer比较127:B2.equals(B1) true
**************************************
Integer与Integer比较127:C1==C2 true
Integer与Integer比较128:C3==C4 false
**************************************
Integer与Integer比较127:E1==E2 true
Integer与Integer比较128:E3==E4 false
**************************************
Integer与Integer比较127:D1==D2 false
Integer与Integer比较128:D3==D4 false
**************************************
解析
两个int比较
两个int比较不用多说,值相等就是true
int与Integer比较
int与Integer比较,先将Integer拆箱,再与int进行值比较;Integer.equals(int)
,使用IDEA打开编译生成的.class文件,发现反编译后是B2.equals(Integer.valueOf(B1))
,先将int装箱后再equals。Integer类的equals被重写,值相等返回true
public boolean equals(Object obj) {
//判断Object是否Integer类型
if (obj instanceof Integer) {
//强转后返回value值比较
return value == ((Integer)obj).intValue();
}
return false;
}
public int intValue() {
return value;
}
equals被重写,那么hashCode()
也需要被重写
@Override
public int hashCode() {
//调用静态方法,最终返回value值
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
int直接赋值Integer后比较
Integer C1 = 127;
将int值直接赋值Integer,会自动装箱,调用Integer.valueOf(int)
public static Integer valueOf(int i) {
//对传入的int进行比较,符合条件的话直接返回已有数组的值
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
//否则调用构造方法
return new Integer(i);
}
IntegerCache
是Integer
的静态内部类。通过源码可以看到,Integer.valueOf(int)
并不是直接根据传入的int值调用构造函数创建对象,而是先进行比较,符合一定条件时,会从已有数组中直接返回。下面是IntegerCache
的源码。
private static class IntegerCache {
// 数组下限
static final int low = -128;
// 数组上限
static final int high;
// 外部使用数组
static final Integer[] cache;
// 静态类内部使用数组
static Integer[] archivedCache;
static {
// high的值可以通过VM的参数间接改变
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
// 最终获得high,默认127
high = h;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
// 最终获得数组[-128~high],high默认127
cache = archivedCache;
// 数组最大值不能小于127
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
通过IntegerCache
的源码可以发现,在类初始化时,IntegerCache
内部会生成一个Integer数组,[-128~high],high默认127。当调用Integer.valueOf(int)
方法(int自动装箱或是手动调用),首先会判断传入的值大小,是否处于数组中,若是,则从数组中直接返回,否则才会new对象。
这也是Integer C1 = 127;
,Integer C2 = 127;
相等的原因。因为127直接赋值Integer,发生自动装箱,调用Integer.valueOf(int)
方法,比较后发现127的大小处于IntegerCache
的数组范围内,直接从此数组返回已有对象,所以此时C1,C2指向的是数组中的同一个对象,所以C1==C2为true。
而Integer C3 = 128;
,Integer C4 = 128;
,由于128大于数组范围,故自动装箱时是return new Integer(i);
,每次都是new出来的新对象,所以C3与C4比较结果为false。
Integer.valueOf(int)
比较
比较结果与自动装箱一致,只不过一个是显式调用Integer.valueOf(int)
,一个隐式调用。
new Integer()比较
每次new出来的都是新对象,比较结果都是false。
总结
-
int与int比较,值相等即为true
-
int与Integer比较,值相等即为true
-
int直接赋值Integer后比较,equals()方法,值相等即为true;
==
比较,默认情况下,当-128<=int<=127
,结果为true,当int<-128或int>127
,结果为false -
调用
Integer.valueOf(int)
,结果与3相同 -
调用
new Integer()
后比较,equals()方法,值相等即为true;==
比较,每次都是生成新对象,结果永远为false