先看这段代码,思考一下返回结果
Integer a1 = Integer.valueOf(1);
Integer b1 = Integer.valueOf(1);
System.out.println(a1 == b1);
System.out.println(a1.equals(b1));
Integer a2 = Integer.valueOf(128);
Integer b2 = Integer.valueOf(128);
System.out.println(a2 == b2);
System.out.println(a2.equals(b2));
实际返回 true,true,false,true,是和你的结果一样吗?
如果不一样建议你仔细看下下面的分析。
先看下Integer的源码对equals方法的重写
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
清楚看到,Integer中equals就是比较值是否相等,因此第2个和第4个都返回true。
那第一个为什么返回true,第三个为什么返回false?
我们接着分析,再看下Integer中的valueOf方法
/**
* 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
*/
@IntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
里面有用到IntegerCache,IntegerCache是个什么东东?再看下IntegerCache源码
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
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 = h;
// Load IntegerCache.archivedCache from archive, if possible
CDS.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;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
哦,原来IntegerCache是Integer对象的缓存池,从jdk1.5开始,Integer内部定义了一个Integer常量池,当创建Integer对象时,不使用new Integer(int i)语句,大小在-128~127之间,对象存放在Integer常量池中。Integer.valueOf(128),刚好超过了常量池,因此新建了一个新的Integer对象。所以第三个结果返回false。
另外从jdk1.6开始,IntegerCache的上限是可以通过jvm启动参数设置的。java.lang.Integer.IntegerCache.high。
总结一下
== 和 equals() 是 Java 中用于比较对象或值是否相等的操作符和方法,但它们在使用和比较的对象类型上有明显的区别。
== 是一个比较操作符,用于比较两个基本数据类型或两个对象的引用是否相等。对于基本数据类型(如 int、float、char 等),== 比较的是值;对于对象引用类型,== 比较的是两个引用是否指向内存中的同一个对象。
equals() 是一个方法,属于java.lang.Object类,所有Java类都继承自这个类,因此所有对象都可以调用 equals() 方法。默认情况下,equals() 方法的行为与 == 相同,即比较两个对象的引用是否相等。但是,许多类(如 String、Integer 等)都重写了 equals() 方法,使其可以比较对象的值而非引用。