我正在比较两段代码。第一
Integer i=3;
Integer j=3;
if(i==j)
System.out.println("i==j"); //prints i==j 第二,
Integer i=3;
Integer j=new Integer(3);
if(i==j)
System.out.println("i==j"); // does not print我怀疑在第一个代码片段中,为什么要打印i==j?引用不应该是不同的吗?
发布于 2013-07-06 01:35:36
这与拳击的工作原理有关。从JLS section 5.1.7
如果要装箱的值p是true、false、\u0000到\u007f之间的字节或字符,或者是-128和127 (含)之间的整数或短数,则r1和r2是p的任意两个装箱转换的结果。r1 == r2始终是这种情况。
基本上,Java实现必须为适当较小的值缓存盒装表示,并且可能缓存更多。==操作符只是比较引用,所以它专门检测这两个变量是否引用同一个对象。在第二个代码片段中,他们肯定不会,因为new Integer(3)绝对不是与之前创建的任何引用相同的引用……它总是创建一个新对象。
由于上述规则,此代码必须始终给出相同的结果:
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // Guarantee to print true然而,这两种情况都有可能发生:
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // Might print true, might print false发布于 2013-07-06 01:34:53
Java池化介于-128和127之间的整数,因此这两个引用是相同的。
Integer i=3;
Integer j=3;这会导致自动装箱,并且3被转换为整数3。因此,因为i引用的是常量池中的整数对象,所以现在当您执行j=3时,将与i的引用相同的引用分配给j。
而下面的代码:
Integer j=new Integer(3);总是导致在堆中创建新的Integer。这不是池化的。因此你可以看到这两个引用都引用了不同的对象。这导致了
Integer i=3;
Integer j=new Integer(3);
if(i==j)
System.out.println("i==j"); // **does not print**发布于 2013-07-06 01:38:50
我怀疑在第一个代码片段中,为什么要打印i==j?引用不应该是不同的吗?
因为,
Integer i=3;
Integer j=3;在内部使用Integer#valueOf()来执行autoBoxing。oracle文档中提到了valueOf()方法:
返回一个表示指定int值的Integer实例。如果不需要新的Integer实例,则通常应优先使用此方法而不是构造函数Integer(int),因为此方法通过缓存频繁请求的值可能会产生显著更好的空间和时间性能。此方法将始终缓存-128到127 (包括-128和127)范围内的值,并可能缓存此范围之外的其他值。
因此,由于值3被缓存,因此变量i和j都引用了同一个对象。因此,i==j将返回true。Integer#valueOf()使用flyweight pattern。
https://stackoverflow.com/questions/17494176
复制相似问题