在 Java 中,Integer
类型的对象比较有一些特殊的规则。特别是当我们使用自动装箱(autoboxing)时,Java 会在一定范围内缓存这些对象,以提高性能和减少内存使用。
自动装箱与拆箱
在 Java 5 之后,引入了自动装箱(autoboxing)和自动拆箱(unboxing)的概念。自动装箱是指将基本数据类型自动转换为对应的包装类对象,而自动拆箱则是将包装类对象自动转换为基本数据类型。
例如:
java
Integer integer1 = 126; // 自动装箱
int int1 = integer1; // 自动拆箱
Integer 缓存机制
为了提高性能和减少内存使用,Java 对 Integer
对象在一定范围内进行了缓存。这个范围通常是 -128 到 127。也就是说,当我们创建一个值在这个范围内的 Integer
对象时,Java 会返回一个缓存的实例,而不是创建一个新的对象。
示例代码
让我们通过一个简单的示例代码来说明这一点:
java
public class Main {
public static void main(String[] args) {
Integer integer1 = 126;
Integer integer2 = 126;
System.out.println(integer1 == integer2); // 输出 true
Integer integer3 = 128;
Integer integer4 = 128;
System.out.println(integer3 == integer4); // 输出 false
}
}
在上面的代码中,我们创建了两个 Integer
对象 integer1
和 integer2
,它们的值都是 126。由于 126 在 -128 到 127 的缓存范围内,Java 会使用缓存的 Integer
对象。因此,integer1
和 integer2
实际上引用的是同一个对象,所以 integer1 == integer2
会返回 true
。
然而,对于 integer3
和 integer4
,它们的值是 128,不在缓存范围内。因此,Java 会创建两个不同的 Integer
对象,所以 integer3 == integer4
会返回 false
。
Integer 缓存的实现
Integer
缓存机制的实现可以在 Integer
类的源码中找到。以下是相关的代码片段:
java
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() {}
}
在 valueOf
方法中,如果传入的整数值在缓存范围内,Java 会返回缓存的 Integer
对象,否则会创建一个新的 Integer
对象。
使用 equals 方法进行比较
在实际开发中,通常建议使用 equals
方法来比较两个 Integer
对象的值,而不是使用 ==
运算符。equals
方法会比较对象的值,而 ==
运算符比较的是对象的引用。
java
public class Main {
public static void main(String[] args) {
Integer integer1 = 128;
Integer integer2 = 128;
System.out.println(integer1.equals(integer2)); // 输出 true
}
}
在这个示例中,integer1
和 integer2
的值都是 128,虽然它们是不同的对象,但 equals
方法会返回 true
,因为它们的值相等。
其他包装类的缓存机制
除了 Integer
之外,其他一些包装类(如 Byte
、Short
、Long
、Character
)也有类似的缓存机制。例如:
Byte
缓存范围是 -128 到 127。Short
缓存范围是 -128 到 127。Long
缓存范围是 -128 到 127。Character
缓存范围是 0 到 127。
这些缓存机制的实现与 Integer
类似,都是为了提高性能和减少内存使用。
结论
Java 中 Integer
缓存机制在一定范围内缓存了 Integer
对象,以提高性能和减少内存使用。理解这一机制对于编写高效的 Java 代码非常重要,特别是在需要频繁使用 Integer
对象的场景中。