【问题标题】:What exactly does comparing Integers with == do?将整数与 == 进行比较究竟有什么作用?
【发布时间】:2010-09-11 03:58:52
【问题描述】:

编辑:好的,好的,我看错了。我没有将 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

什么给了?

【问题讨论】:

  • 看,我不确定这本书的这部分是写得不好还是我是个白痴,但我就是不知道它说的原因是什么。我最好的理解尝试是 == 与 != 的处理方式不同。也许 == 反映了价值平等(深度平等),但 != 没有。无论如何,书上所说的无论如何都不会发生。
  • 不,这种情况下的问题在于您要比较的两种类型。 == 和 != 的行为方式相同。
  • 仅仅这个例子就足以让我觉得 Java 是某种恶作剧而不是真正的编程语言。
  • @dsimcha - 这是一个非常蹩脚的说法。如果要比较两个整数指针,在 C 语言中可能会遇到同样的问题 - 它更明确。
  • 您的第二个示例确实打印了true。见ideone

标签: java compare wrapper


【解决方案1】:

另请注意,较新版本的 Java 缓存 Integers 在 -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),但如果您将两个 Integers 与 == 进行比较,则将因@dan04 解释的原因而失败。

【讨论】:

  • 有趣!我永远不会使用 == IRL,但这是我们正在谈论的非常虐待狂的考试 :)
  • +1 表示非常相关的点。我会挑剔并指出它是-128 to 127,尽管 Sun JDK 附带的 1.6 源代码显示他们玩游戏的上限是上限(但始终至少为 127)。
【解决方案2】:
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);

因为这些是用编译时常量初始化的,所以编译器可以并且确实对它们进行内部处理,并使它们都指向同一个 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);

(你猜后,run it and see!

【讨论】:

  • 这很重要,因为只保留小整数。 - 请记住,Integer 只是维护一个内部缓存,它在以下情况下使用(用于所述小值)调用valueOf;编译器仍然会生成两行invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;
【解决方案3】:

你不是在比较一个原语和一个包装器。您正在比较两个包装器(引用类型)。 == 比较对象标识,返回 false 因为它们是不同的对象。

【讨论】:

  • 并非总是如此,较小的整数值会被缓存,就像您调用 Integer.valueOf 一样。所以你实际上是在比较相同的对象。
【解决方案4】:

不,我认为代码打印不正确,你自己回答了为什么。

当 == 用于比较原语时 对于包装器,包装器将是 展开,比较将是 原始到原始。

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

【讨论】:

    【解决方案5】:

    请注意,您误读了您引用的摘录。摘录特别将它的陈述限制为如下比较:

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

    【讨论】:

      【解决方案6】:

      从 Java 5.0 开始,有自动装箱和拆箱,这意味着包装器可以隐式转换为原语,反之亦然。但是,如果您比较两个 Integer 对象,您仍然在比较两个引用,并且没有什么会触发自动装箱/拆箱。如果是这样的话,用 J2SE 1.4 和之前的版本编写的代码就会出错。

      【讨论】:

        【解决方案7】:

        假设我们有一个例子

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

        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 之间的值。

        当您使用“==”运算符比较两个整数对象时,如果这两个整数对象是使用自动装箱创建的,则将调用 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) 返回错误

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-21
          • 1970-01-01
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-05
          • 1970-01-01
          相关资源
          最近更新 更多