关于自动装箱和对象相等/同一性的Java问题

发布于 2024-09-11 22:45:10 字数 523 浏览 2 评论 0原文

public class Main { 
    /** 
      * @param args the command line arguments */ 
    public static void main(String[] args) { 
        // TODO code application logic here
        int a1 = 1000, a2 = 1000; 
        System.out.println(a1==a2);//=>true 
        Integer b1 = 1000, b2 = 1000;
        System.out.println(b1 == b2);//=>false 
        Integer c1 = 100, c2 = 100; 
        System.out.println(c1 == c2);//=>true 
    }

}

为什么b1 == b2为假而c1 == c2为真?

public class Main { 
    /** 
      * @param args the command line arguments */ 
    public static void main(String[] args) { 
        // TODO code application logic here
        int a1 = 1000, a2 = 1000; 
        System.out.println(a1==a2);//=>true 
        Integer b1 = 1000, b2 = 1000;
        System.out.println(b1 == b2);//=>false 
        Integer c1 = 100, c2 = 100; 
        System.out.println(c1 == c2);//=>true 
    }

}

Why is b1 == b2 false and c1 == c2 true?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

写下不归期 2024-09-18 22:45:11

阅读本文

Java 对 -128 到 127 范围内的 Integer 使用

这意味着如果您使用 Integer i 创建一个 Integer = 42;且其值在-128到128之间,没有创建新对象,但从池中返回相应的对象。这就是为什么 c1 确实与 c2 相同

我假设您知道 == 在应用于对象时比较引用,而不是值)。

Read this.

Java uses a pool for Integers in the range from -128 to 127.

That means if you create an Integer with Integer i = 42; and its value is between -128 and 128, no new object is created but the corresponding one from the pool is returned. That is why c1 is indeed identical to c2.

(I assume you know that == compares references, not values, when applied to objects).

网名女生简单气质 2024-09-18 22:45:11

正确答案已经给出。但我想补充两点:

Integer b1 = 1000, b2 = 1000;

这是糟糕的代码。对象应该通过构造函数或工厂方法初始化为对象。 Eg

 // let java decide if a new object must be created or one is taken from the pool
Integer b1 = Integer.valueOf(1000);

 // always use a new object
 Integer b2 = new Integer(1000);

此代码

Integer b1 = 1000, b2 = 1000;

另一方面, 暗示 Integer 是原语,但事实并非如此。实际上,您看到的是 Integer 的快捷方式

Integer b1 = Integer.valueOf(1000), b2 = Integer.valueOf(1000);

,并且 Integer 仅池化从 -127 到 127 的对象,因此在这种情况下它将创建两个新对象。因此,虽然 1000 = 1000,但 b1 != b2。这就是我讨厌自动装箱的主要原因。

The correct answers have already been given. But just to add my two cents:

Integer b1 = 1000, b2 = 1000;

This is awful code. Objects should be initialized as Objects through constructors or factory methods. E.g.

 // let java decide if a new object must be created or one is taken from the pool
Integer b1 = Integer.valueOf(1000);

or

 // always use a new object
 Integer b2 = new Integer(1000);

This code

Integer b1 = 1000, b2 = 1000;

on the other hand implies that Integer was a primitive, which it is not. Actually what you are seeing is a shortcut for

Integer b1 = Integer.valueOf(1000), b2 = Integer.valueOf(1000);

and Integer only pools objects from -127 to 127, so it will create two new Objects in this case. So although 1000 = 1000, b1 != b2. This is the main reason why I hate auto-boxing.

好多鱼好多余 2024-09-18 22:45:11

因为 Integer 用于一些低数字,例如枚举,所以总是存在相同的实例。但较大的数字会创建 Integer 的新实例,并且运算符 == 会比较它们的引用

Because Integer is for a few low numbers like enumeration so there is always same instance. But higher numbers creates new instances of Integer and operator == compares their references

ζ澈沫 2024-09-18 22:45:11

您可以在这里找到答案:

第 6 个答案中的最奇怪的语言功能

编辑:抱歉,不完全是答案。要点是,当您将 == 与 Integer 一起使用时,它比较的是引用,而不是值。但 int "==" 表示等于。

You can find the answer here:

Strangest language feature in the 6th answer.

Edit: sorry not exatly the answer. The point is that == compares references, not values when you use it with Integer. But with int "==" means equals.

七度光 2024-09-18 22:45:11
  public static Integer valueOf(int i) {
      final int offset = 128;
      if (i >= -128 && i <= 127) { // must cache
          return IntegerCache.cache[i + offset];
      }
       return new Integer(i);
    }

因此,你在一种情况下是正确的,在另一种情况下是错误的!

  public static Integer valueOf(int i) {
      final int offset = 128;
      if (i >= -128 && i <= 127) { // must cache
          return IntegerCache.cache[i + offset];
      }
       return new Integer(i);
    }

Because of this you true in one case, and false in other!

森末i 2024-09-18 22:45:11

您想要的答案在这里

The answer you want is here

ぺ禁宫浮华殁 2024-09-18 22:45:11

如果在使用 '==' 运算符进行相等性检查时自动拆箱也起作用,您可以编写:

    Long notNullSafeLong1 = new Long(11L)
    Long notNullSafeLong2 = new Long(22L)
    if ( notNullSafeLong1 == notNullSafeLong2) {
      do suff

这将需要实现 == 的覆盖,以便 null==someLong 为 false,特殊情况 Null==Null 为 true。相反,我们必须使用 equal() 并测试 null

    Long notNullSafeLong1 = new Long(11L)
    Long notNullSafeLong2 = new Long(22L)
    if ( (notNullSafeLong1 == null && notNullSafeLong2 == null) || 
      (notNullSafeLong1 != null && notNullSafeLong2 != null & 
        notNullSafeLong1.equals(notNullSafeLong2)) {
      do suff    

这比第一个示例更详细 - 如果自动拆箱适用于 '==' 运算符。

If autounboxing had worked also when doing equality checking with the '==' operator you could write:

    Long notNullSafeLong1 = new Long(11L)
    Long notNullSafeLong2 = new Long(22L)
    if ( notNullSafeLong1 == notNullSafeLong2) {
      do suff

This would require implementing an override for == so that null==someLong is false and the special case Null==Null is true. Instead we have to use equal() and test for null

    Long notNullSafeLong1 = new Long(11L)
    Long notNullSafeLong2 = new Long(22L)
    if ( (notNullSafeLong1 == null && notNullSafeLong2 == null) || 
      (notNullSafeLong1 != null && notNullSafeLong2 != null & 
        notNullSafeLong1.equals(notNullSafeLong2)) {
      do suff    

This is alittle more verbose than the first example - if autounboxing had worked for the '==' operator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文