在 Java 面试中,经常会遇到关于 Integer
对象创建和缓存机制的问题。例如,new Integer("127")
和 Integer.valueOf("128")
的区别。这个问题触及了 Java 中整数缓存机制的一个微妙之处。
Integer
对象。Integer
对象,值为 128。new Integer("127")
不使用缓存。Integer.valueOf("128")
也不使用缓存,但原因不同(超出范围).new
关键字绕过了缓存.valueOf
方法会创建新对象.Integer a = new Integer("127");
Integer b = new Integer("127");
System.out.println(a == b); // false
Integer c = Integer.valueOf("127");
Integer d = Integer.valueOf("127");
System.out.println(c == d); // true
Integer e = Integer.valueOf("128");
Integer f = Integer.valueOf("128");
System.out.println(e == f); // false
···
# 为什么 Integer.valueOf("128") 也不使用缓存?
## Integer 缓存是什么?
- **定义**:Java 的 `Integer` 类维护了一个内部缓存,用于存储经常使用的整数值。这个缓存就像一个预先准备好的数字集合.
- **默认范围**:默认情况下,这个缓存包含了 -128 到 127 之间的所有整数.
## 为什么是 -128 到 127?
- **字节范围**:这个范围恰好对应一个字节(byte)可以表示的整数范围.
- **常用数字**:大多数日常计算和循环中使用的小整数都在这个范围内.
- **内存权衡**:缓存范围不能太大,否则会占用过多内存.
## 为什么 128 不在缓存中?
- **超出范围**:128 刚好超出了这个预定义的范围.
- **创建新对象**:当你调用 `Integer.valueOf("128")` 时,Java 会检查这个数字是否在缓存范围内。发现 128 超出范围后,Java 就会创建一个新的 `Integer` 对象,而不是使用缓存.
# 代码示例
```java
Integer a = Integer.valueOf("127"); // 使用缓存
Integer b = Integer.valueOf("127"); // 使用缓存
System.out.println(a == b); // 输出 true,因为是同一个缓存对象
Integer c = Integer.valueOf("128"); // 不使用缓存,创建新对象
Integer d = Integer.valueOf("128"); // 不使用缓存,再次创建新对象
System.out.println(c == d); // 输出 false,因为是两个不同的对象
-XX:AutoBoxCacheMax=
来增加上限..equals()
方法来比较 Integer
对象的值.虽然在给定的例子中(“127” 和 “128”),两种方法都会创建新对象,但它们的行为原因不同:
new Integer("127")
总是创建新对象,无论值是多少.Integer.valueOf("128")
创建新对象是因为 128 超出了缓存范围.在实际应用中,除非特别需要新对象,否则推荐使用 Integer.valueOf()
或自动装箱,以便在可能的情况下利用缓存优化。虽然了解这些细节很重要,但在日常编程中,我们应该专注于编写清晰、正确的代码,而不是过度依赖于这些底层优化。正确使用 .equals()
进行值比较,以及优先使用 valueOf()
或自动装箱,通常就足以编写高效且可靠的代码.