整数i = 3 vs Integer i = new Integer(3)

时间:2013-07-05 17:32:18

标签: java

我正在比较2段代码。首先

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?参考文献不应该有所不同吗?

9 个答案:

答案 0 :(得分:18)

这与拳击工作有关。来自JLS section 5.1.7

  

如果装箱的值p为真,假,字节或范围为\ 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

答案 1 :(得分:6)

Java池整数介于-128和127之间,因此两个引用都是相同的。

Integer i=3;
Integer j=3;

这导致自动装箱,并且3被转换为整数3.因此,对于i,指的是处于常量池中的Integer对象,现在当你执行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**

答案 2 :(得分:3)

Integer i=3;
Integer j=3;
if(i==j)System.out.println("i==j");

此处,3正在自动装箱,因此ij指向同一Integer

Integer i=3;
Integer j=new Integer(3);
if(i==j)System.out.println("i==j"); // does not print

此处,i指向自动装箱的Integer,而j指向新的Integer,因此引用无法通过等于==运算符测试

但是,这里还有一些值得思考的东西。

Integer i=300;
Integer j=300;
if(i!=j)System.out.println("i!=j"); // prints i!=j

为什么呢?因为,自动装箱仅在-128到127之间共享Integer个实例。但是,这种行为在不同的Java实现之间可能会有所不同。

答案 3 :(得分:2)

  

我怀疑在第一个片段中为什么i == j正在打印?   参考文献不应该有所不同吗?

由于,

    Integer i=3;
    Integer j=3;

在内部使用Integer#valueOf()来执行autoBoxing。 oracle doc说valueOf()方法:

  

返回表示指定int值的Integer实例。如果一个   新的Integer实例不是必需的,这个方法一般应该是   优先使用构造函数Integer(int),就像这个方法一样   可能会产生明显更好的空间和时间表现   缓存频繁请求的值。 此方法将始终缓存   值范围为-128到127(包括),并可以缓存其他值   超出此范围。

因为值3被缓存,所以变量ij都引用同一个对象。因此,i==j正在返回trueInteger#valueOf()使用flyweight pattern

答案 4 :(得分:1)

不,他们不应该,因为java可以在自动装箱时使用预制的Integer对象来获取小数字。

答案 5 :(得分:0)

因为在第二个代码中你的第一个整数是自动装箱的,而第二个不是。

这意味着即时创建一个新的Integer实例。这两个对象实例是不同的。由于两个实例实际上是不同的内存块,因此相等性检查将返回false。

答案 6 :(得分:0)

Interpreter / JIT优化器可以将所有3个放在同一个框中。但是如果你强迫一个“新”,那么你会得到另一个地址。

尝试

 j=8; // after initialization of i and j

然后看到j的地址已更改为第一个版本。

答案 7 :(得分:0)

类似方式使用字符串时,使用自动装箱时,例如

Integer i = 3;
Integer j = 3;

Java可以从预制对象池中提取。在j的情况下,已经有一个Integer实例表示池中3的值,因此它从中抽取。因此,ij指向相同的事物,因此i == j

在第二个示例中,您明确地为Integer实例化了一个新的j对象,因此ij指向不同的对象,因此{{1} }。

答案 8 :(得分:0)

在下面的代码中:

Integer i=3;
Integer j=3;
if(i==j)
   System.out.println("i==j");

这里,“==”比较参考值而不是值。 因此,Integer i和j都指的是内存中的相同引用。

在下面的代码中:

Integer i=3;
Integer j=new Integer(3);
if(i==j)
   System.out.println("i==j");

对两个值的引用都会更改,因为'j'是内存中新生成的Integer对象/引用,而'i'只是指一个值。

因此,第一个代码的输出是“i == j”,第二个代码没有任何输出。

希望这有帮助。