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

时间:2010-09-11 03:58:53

标签: java compare wrapper

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

我的SCJP书说:

  

当==用于比较基元时   对于包装器,包装器将是   打开并进行比较   原始到原始。

所以你认为这段代码会打印true

    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

是什么给出了?

7 个答案:

答案 0 :(得分:12)

另请注意,较新版本的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);

将打印truefalse。 (见ideone

道德:为避免出现问题,请在比较两个对象时始终使用.equals()

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

答案 1 :(得分:8)

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

当您将{1}}分配给该值时,会创建一个i1对象。然后比较比较两个对象引用。引用不相等,因此比较失败。

Integer

因为这些是使用编译时常量初始化的,所以编译器可以并且实际执行它们并使两者都指向相同的Integer i1 = 100; Integer i2 = 100; System.out.println(i1 != i2); 对象。

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


这是一个非常有趣的测试。看看你是否能解决这个问题。为什么第一个程序会打印Integer,但第二个程序会打印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);

(您猜后,run it and see!

答案 2 :(得分:6)

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

答案 3 :(得分:1)

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

  

当==用于比较基元时   对于包装器,包装器将是   打开并进行比较   原始到原始。

然后你继续比较两个整数引用 - 也就是说,它比较了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);

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

假设我有一个例子

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

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。 Integer类将值缓存在-128到127之间。

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

ANSWER:False True False False

以下是该方法的实施

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

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