2012-03-22 58 views
11

下面的代码似乎让我很困惑,因为它提供了两个不同的输出。代码在jdk 1.7上进行了测试。How!=和==运算符在Java中的Integers上工作吗?

public class NotEq { 

public static void main(String[] args) { 

    ver1(); 
    System.out.println(); 
    ver2(); 
} 

public static void ver1() { 
    Integer a = 128; 
    Integer b = 128; 

    if (a == b) { 
     System.out.println("Equal Object"); 
    } 

    if (a != b) { 
     System.out.println("Different objects"); 
    } 

    if (a.equals(b)) { 
     System.out.println("Meaningfully equal."); 
    } 
} 

public static void ver2() { 
    Integer i1 = 127; 
    Integer i2 = 127; 
    if (i1 == i2) { 
     System.out.println("Equal Object"); 
    } 

    if (i1 != i2){ 
     System.out.println("Different objects"); 
    } 
    if (i1.equals(i2)){ 
     System.out.println("Meaningfully equal"); 
    } 
} 

} 

输出:

[VER1输出]
不同的对象
有意义相等。

[VER2输出]
平等对象
有意义等于

为什么==和!=测试产生用于VER1()和VER2()为相同数目大于整数小得多不同的结果。 MAX_VALUE?是否可以得出结论:==检查大于127的数字(如代码中所示的Integer等包装类)是否完全浪费时间?

+3

这是因为自动装箱机制缓存和重新使用范围-128 - 127中的值的同一对象。这是上一个问题的重复。 – aioobe 2012-03-22 14:16:36

+0

@quixoto:看我的编辑回复:) – BoltClock 2012-03-22 14:41:54

+1

http://stackoverflow.com/questions/1700081/why-does-128-128-return-false-but-127-127-return-true-when-converting-to -integ – 2016-02-17 13:16:56

回答

10

整数缓存的值介于-128和127之间,因此Integer i = 127将始终返回相同的引用。 Integer j = 128不一定会这样做。然后您将需要使用equals来测试相关的int的平等。

这是Java Language Specification的一部分:

如果被装箱值p为真,假,字节,或在范围\ u0000的一个char到\ u007f之间,或在一个int或短号码-128和127(含),那么令r1和r2是p的任何两次装箱转换的结果。 r1 == r2总是如此。

但2调用Integer j = 128可能返回相同的附图(不保证):

更少的内存限制的实施方式中可能,例如,高速缓存的所有char和短的值,以及int和长值在-32K到+ 32K范围内。

+0

虽然构造函数不使用缓存。尝试:System.out.println(new Integer(2)== new Integer(2)) – fgb 2012-03-22 14:25:04

+1

'new Integer(127)'永远不会返回相同的引用。实际上,它确保始终创建一个新对象。但是当像“Integer i = 127;”那样使用自动装箱时,则使用缓存。顺便说一句,上边界127不是固定的,而是最小的。它可以配置为更大的值,但不能更低。 – 2012-03-22 14:27:30

4

由于小整数在Java中被执行,并且您尝试了“小”限制的不同侧上的数字。

+0

@downvoter,你愿意详细说明你的投票吗? – dasblinkenlight 2012-03-22 14:41:22

0

Java缓存从-128到127的整数这就是为什么对象是相同的。

0

我认为==和!=运算符在处理基元时会如何使用它们,但对于对象(整数与int),您将需要使用.equals()方法执行测试。如果一个对象是相同的对象,而.equals()将执行测试,这两个对象在值中包含等价(或方法将需要创建/重写)自定义对象。

3

默认情况下存在一个从-128到127的Integer对象缓存。上边框可以配置。上高速缓存的边界可以通过VM选项控制-XX:AutoBoxCacheMax=<size>

您使用此缓存,当您使用以下形式:

Integer i1 = 127; 

Integer i1 = Integer.valueOf(127); 

但是当你使用

Integer i1 = new Integer(127); 

那么你保证会得到一个新的未缓存的对象。在后一种情况下,两个版本都打印出相同的结果。使用缓存版本他们可能会有所不同。

+0

很高兴知道。请不要在生产中这样做。 – atamanroman 2015-03-02 11:52:25