2015-11-24 62 views
6

我比较两段代码爪哇 - 拳击整数 - 为什么它返回true,如果应该返回false

Integer x = new Integer(0), y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints false 

而且

Integer x = 0, y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints true 

不应同时返回false?这不是原始变量,并且在第二个代码中,即使在添加零后,它也会打印true。我知道拳击(整数从-128到127),但是为什么拳击在第二段代码而不是在第一段?

+1

不,因为在'-128 - 127'范围内的Integer会被缓存。在你的第一个例子中,你明确地创建了一个新的'Integer',尽管每个'Integer'在'-128 - 127'范围内都会引用同一个对象。 – SomeJavaGuy

+0

尽管还有其他回答说-128-127不是教条,它只是JVM的一个功能,可以在一些版本中使用-Djava.lang.Integer.IntegerCache.high属性进行调整,默认值可能与JVM到JVM,**你永远不应该依赖这种行为!**请参阅http:// stackoverflow。com/questions/15052216/how-large-is-the-integer-cache –

回答

16

不应该都返回false?

线

x += 0; 

相同

x = Integer.valueOf(x.intValue() + 0); 

让你看到它使用装箱和拆箱来完成操作。


第二个示例仅使用装箱,因此它按预期工作。

在第一个例子,你明确地避免装箱与

Integer x = new Integer(0); 

这迫使它来建立一个新的对象,它是对装箱对象不同。

如果你

Integer x = Integer.valueOf(0); 

它的行为一样的第二个例子。

+0

也许如果编译器足够聪明,它可能会忽略增加'0'? – TheLostMind

+0

@VinodMadyalkar是的,但它有这样的副作用。 Java很不情愿地打破兼容性,即使它没有太大的意义恕我直言。注意:'x + = 0f'确实对某些值做了一些事情,或许令人惊讶。 –

+0

我在评论之前就已经想过了。但是编译器肯定可以在正常情况下(比如在问题中)做:)。这可能会阻止几个字节码指令 – TheLostMind

5

不,因为在-128 - 127范围内的整数正在缓存。在第一个示例中,您明确地创建了一个新的整数,尽管-128 - 127范围内的每个整数都会引用同一个对象。

如果您在第一个示例中添加了某些内容,则可以通知您。 通知,这将只在Integer范围-128 - 127

Integer x = new Integer(0), y; 
Integer z = 0; // refers to the cached value. 
y=x; 
x+=0; 
System.out.println(x==z); // This will now print true, since x+=0 will return the cached Integer. 

工作,你的第二个例子不会藏汉如果将值x更改为不同的工作了,例如360

1

因为,

整数x是一个对象。 因此==,比较参考和不值。

INT x不是一个对象 所以==,比较值

您简单的代码:

Integer x = new Integer(0), y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints false 
System.out.println(x.equals(y)); // prints true 

int x1, y1; 
x1 = 5; 
y1 = x1; 

System.out.println(x1==y1); // prints true 
System.out.println(((Integer) x1).equals(y1)); //prints true 

和结果:

  • 真正
  • 个真正

问候

行 - 我已经看到了javap的(感谢您的答案)的响应,我明白我错过了。但是,我发现我提出的一段代码仍然很有趣。

+1

我想你没有得到提问者问题的本质。他很惊讶,为什么第二个例子返回true。 – Michal

3

[更新]使用new Integer(int)是保证总是产生一个新的对象,而Integer.valueOf(int)允许值的高速缓存到由编译器,类库,JVM或来完成。

为了解释我写下面的代码,并使用javap工具,命令生成下面的代码我使用了javap -c <Classname>它给你字节码。

Integer x = new Integer(0), y; 
    y=x; 
    x+=0; 
    System.out.println(x==y); // prints false 

enter image description here

如果你在上面的代码中看到它创建了动态内存分配是new新的对象。现在,在如下第二种情况:

Integer x = 0, y; 
    y=x; 
    x+=0; 
    System.out.println(x==y); // prints true 

enter image description here

如由Peter说,它使用valueOf方法这意味着它是比较在运行时相同的对象,以便它将返回true与对象比较运算符(==)。但是,在第一种情况下它是创造新的对象,它是在下面的调试快照显眼:

enter image description here

我希望这有助于。 :)

顺便凯文埃斯凯答案也增加了这个问题。因为它基本上引用了缓存对象,所以尝试在String的情况下将其与它关联。如果您使用的是new String("some_string"),则会创建新对象,如果可用,则将使用string pool。并且记住你正在使用不是原始的包装类。

相关问题