我知道在该主题上也有类似的帖子,但是它们并没有完全解决我的问题。当您这样做时:
Integer a = 10; Integer b = 10; System.out.println("a == b: " + (a == b));
(显然)true大多数时间都会打印,因为以某种方式缓存了[-128,127]范围内的整数。但:
true
Integer a = new Integer(10); Integer b = new Integer(10); System.out.println("a == b: " + (a == b));
会回来的false。我知道我正在请求一个Integer的新实例,但是由于装箱的原语在Java中是不可变的,并且已经有了执行“正确的事情”的机制(如第一种情况所示),为什么会发生这种情况?
false
如果Integer的所有实例(具有10)都在内存中是同一对象,这是否更有意义?换句话说,为什么我们没有类似于“字符串实习”的“整数实习”?
更好的是,如果代表盒装基元的实例代表相同事物( 无论其值(和类型)如何) 是同一对象,这是否更有意义?或至少正确回应==?
==
非常清楚的是,缓存会对性能造成不可接受的影响–每次创建Integer时,都会产生额外的if语句和内存查找。仅此一个因素就掩盖了任何其他原因,而使该线程感到痛苦的其余部分。
就“正确”响应==而言,OP在其正确性假设中是错误的。整数确实通过Java社区对正确性的期望,当然也通过规范对正确性的定义,对==做出正确的响应。也就是说,如果两个引用指向同一对象,则它们为==。如果两个引用指向 不同的 对象,即使它们具有相同的内容,它们 也不 ==是相同的。因此,得出的结果就不足为奇new Integer(5) == newInteger(5)了false。
new Integer(5) == newInteger(5)
更为有趣的问题是, 为什么 new Object();每次都需要创建一个唯一的实例?即为什么newObject();不允许缓存?答案是wait(...)和notify(...)。缓存new Object()s会错误地导致线程在不应该同步时彼此同步。
new Object();
newObject();
wait(...)
notify(...)
new Object()
如果不是那样的话,那么Java实现可以完全new Object()单例缓存s。
new Integer(5)这就说明了为什么必须创建7个唯一的Integer对象(每个对象都包含值5 )需要完成7次(因为Integerextend Object)。
new Integer(5)
Integer
Object
次要的,不太重要的东西: 自动装箱和自动拆箱功能导致本来不错的方案中的一个问题。没有该功能,您将无法进行比较new Integer(5) == 5。要启用这些功能,Java 会将 对象 取消装箱 (并且 不对 原语进行装箱)。因此new Integer(5) == 5被转换为:(new Integer(5).intValue() == 5而 不是 new Integer(5) == newInteger(5)。
new Integer(5) == 5
new Integer(5).intValue() == 5
最后一两件事要了解是那个自动装箱n时 不 被做new Integer(n)。通过内部调用来完成Integer.valueOf(n)。
n
new Integer(n)
Integer.valueOf(n)
如果您认为自己了解并想要测试自己,请预测以下程序的输出:
public class Foo { public static void main (String[] args) { System.out.println(Integer.valueOf(5000) == Integer.valueOf(5000)); System.out.println(Integer.valueOf(5000) == new Integer(5000)); System.out.println(Integer.valueOf(5000) == 5000); System.out.println(new Integer(5000) == Integer.valueOf(5000)); System.out.println(new Integer(5000) == new Integer(5000)); System.out.println(new Integer(5000) == 5000); System.out.println(5000 == Integer.valueOf(5000)); System.out.println(5000 == new Integer(5000)); System.out.println(5000 == 5000); System.out.println("====="); System.out.println(Integer.valueOf(5) == Integer.valueOf(5)); System.out.println(Integer.valueOf(5) == new Integer(5)); System.out.println(Integer.valueOf(5) == 5); System.out.println(new Integer(5) == Integer.valueOf(5)); System.out.println(new Integer(5) == new Integer(5)); System.out.println(new Integer(5) == 5); System.out.println(5 == Integer.valueOf(5)); System.out.println(5 == new Integer(5)); System.out.println(5 == 5); System.out.println("====="); test(5000, 5000); test(5, 5); } public static void test (Integer a, Integer b) { System.out.println(a == b); } }
为了获得额外的信用,如果所有值==都更改为,还可以预测输出.equals(...)
.equals(...)
更新: 感谢用户@sactiw的评论:“缓存的默认范围是-128到127,并且从Java 1.6开始,您可以通过从命令行传递- XX:AutoBoxCacheMax =来重置上限值> = 127”