将Integers与==进行比较究竟做了什么?

编辑:好的,好的,我误读了。 我不是将int与Integer进行比较。 正好指出。

我的SCJP书说:

当==用于将基元与包装器进行比较时,包装器将被解包,并且比较将是原始的。

所以你认为这段代码会打印出来:

  Integer i1 = 1; //if this were int it'd be correct and behave as the book says. Integer i2 = new Integer(1); System.out.println(i1 == i2); 

但它打印false

另外,根据我的书,这应该打印为true

 Integer i1 = 1000; //it does print `true` with i1 = 1000, but not i1 = 1, and one of the answers explained why. Integer i2 = 1000; System.out.println(i1 != i2); 

不。 这是false

是什么赋予了?

 Integer i1 = 1; Integer i2 = new Integer(1); System.out.println(i1 == i2); 

i1分配1时,该值被装箱,创建一个Integer对象。 然后比较比较两个对象引用。 引用不相等,因此比较失败。

 Integer i1 = 100; Integer i2 = 100; System.out.println(i1 != i2); 

因为这些是使用编译时常量初始化的,所以编译器可以并且实际执行它们并使两者都指向相同的Integer对象。

(注意,我将值从1000更改为100.正如@NullUserException指出的那样,只有小整数被实现。)


这是一个非常有趣的测试。 看看你是否可以解决这个问题。 为什么第一个程序打印为true ,但第二个程序为false ? 利用您对拳击和编译时间分析的了解,您应该能够解决这个问题:

 // Prints "true". int i1 = 1; Integer i2 = new Integer(i1); System.out.println(i1 == i2); // Prints "false". int i1 = 0; Integer i2 = new Integer(i1); i1 += 1; System.out.println(i1 == i2); 

如果您了解上述内容,请尝试预测此程序打印的内容:

 int i1 = 0; i1 += 1; Integer i2 = new Integer(i1); System.out.println(i1 == i2); 

(你猜后, 跑吧看看! )

另请注意,较新版本的Java缓存Integer在-128到127范围内(256个值),这意味着:

 Integer i1, i2; i1 = 127; i2 = 127; System.out.println(i1 == i2); i1 = 128; i2 = 128; System.out.println(i1 == i2); 

会打印出false 。 (在ideone上看到它)

道德:为了避免问题,在比较两个对象时总是使用.equals()

当您使用==将包装的基元与基元(例如: Integerint )进行比较时,您可以依赖取消装箱,但如果您要将两个Integer==进行比较,这将因为@ dan04解释的原因而失败。

您没有将基元与包装器进行比较。 您正在比较两个包装器(引用类型)。 ==比较对象标识,它返回false因为它们是不同的对象。

不,我不认为代码打印是真的,你回答了自己的确切原因。

当==用于将基元与包装器进行比较时,包装器将被解包,并且比较将是原始的。

然后你继续比较两个整数引用 – 也就是说,它比较了i1和i2的内存地址。 你也想要

 Integer i1 = 1; Integer i2 = new Integer(1); System.out.println(i1.equals(i2)); 

要么

 int i1 = 1; Integer i2 = new Integer(1); System.out.println(i1 == i2); 

请注意,您误读了所引用的摘录。 摘录明确地将其声明限制为这样的比较:

 int k = 1; Integer l = new Integer(1); System.out.println(l == k); 

从Java 5.0开始,有自动装箱和拆箱,这意味着包装器可以隐式转换为基元,反之亦然。 但是,如果比较两个Integer对象,则仍在比较两个引用,并且没有任何内容会触发自动装箱/取消装箱。 如果是这种情况,用J2SE 1.4和之前编写的代码就会破坏。

假设我们有一个例子

这个程序代码的输出是什么?

 public class autoboxing { public static void main(String a args) { Integer a = new Integer(127); Integer b = new Integer(127); Integer c = 127; Integer d = 127; Integer e = new Integer(200); Integer f = new Integer(200); Integer g = 200; Integer h = 200; System.out.println((a == b) + ' " + (c =-- d) + " " + (e==f)+ " "+ (g == h)); 

使用new运算符创建Integer对象时,每次都返回一个新对象。 当您使用“==”运算符比较两个引用变量时,如果两个引用变量引用两个不同的对象,则“==”运算符返回false。

所以,

(a == b)和(e == f)表达式返回false。 整数类缓存介于-128到127之间的值。

当您使用“==”运算符比较两个Integer对象时,如果使用自动装箱创建这两个整数对象,则将调用value0f(int i)方法。

答案:错误真假

以下是该方法的实现

 public static Integer value0f(int i) { if (i >= IntegerCachedow && i <= IntegerCache.high) return IntegerCache.cacheli + (-IntegerCachedow)); return new Integer(i); 

从上面的实现,下面是结论

  1. 如果两个Integer对象值介于-128到127之间,则此方法返回相同的值。 所以(c == d)返回true。

  2. 如果两个Integer对象值超出-128到127的范围,则此方法返回不同的新Integer对象。 所以,(g == h)返回false

有关此方法的更多详细信息,请访问: https : //stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127