【问题标题】:Java question about autoboxing and object equality / identity [duplicate]关于自动装箱和对象相等/身份的Java问题[重复]
【发布时间】:2010-07-28 10:09:48
【问题描述】:
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 为真?

【问题讨论】:

    标签: java integer autoboxing


    【解决方案1】:

    阅读this

    Java 为Integers 使用 pool,范围从 -128 到 127。

    这意味着如果你用Integer i = 42; 创建一个Integer 并且它的值在-128 和128 之间,no 新对象被创建但从池中返回对应的对象。这就是为什么c1c2 确实相同

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

    【讨论】:

    • 非常感谢 Felix Kling。我看懂了这段代码
    • 这并不能解释为什么 a1==a2。
    • 如果我没记错的话,问题是关于b1==b2c1==c2
    • a1==a2 因为它们是原始的“int”类型,而不是 Integer 对象类型
    • 范围在 - 128 到 127 之间。
    【解决方案2】:

    已经给出了正确的答案。但只是为了增加我的两分钱:

    Integer b1 = 1000, b2 = 1000;
    

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

     // 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 b1 = Integer.valueOf(1000), b2 = Integer.valueOf(1000);
    

    而 Integer 只对 -127 到 127 的对象进行池化,所以在这种情况下它会创建两个新的对象。所以虽然 1000 = 1000,但 b1 != b2。这就是我讨厌自动装箱的主要原因。

    【讨论】:

    • >This is awful code. Objects should be initialized as Objects through constructors or factory methods. 这并不完全正确。当您创建 String 的实例时,最佳做法是编写 String str = "str";
    • @Rob 确实如此。另外,这个答案很老了,不确定我今天会写同样的内容
    【解决方案3】:

    因为 Integer 用于枚举等一些低数字,所以总是有相同的实例。但是更大的数字会创建 Integer 的新实例,并且 operator == 会比较它们的引用

    【讨论】:

      【解决方案4】:

      你可以在这里找到答案:

      Strangest language feature 在第 6 个答案中。

      编辑:对不起,答案不是很清楚。关键是 == 比较引用,而不是与 Integer 一起使用时的值。但是 int "==" 表示等于。

      【讨论】:

        【解决方案5】:
          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);
            }
        

        因此,您在一种情况下为真,在另一种情况下为假!

        【讨论】:

        • +1 来自来源的此报价。也是范围正确的第一个答案!
        【解决方案6】:

        你要的答案是here

        【讨论】:

          【解决方案7】:

          如果在使用“==”运算符进行相等检查时自动拆箱也有效,您可以编写:

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

          这需要实现对 == 的覆盖,以便 null==someLong 为假,而特殊情况 Null==Null 为真。相反,我们必须使用 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    
          

          这比第一个示例更详细 - 如果自动拆箱对 '==' 运算符有效。

          【讨论】:

            猜你喜欢
            • 2018-06-20
            • 1970-01-01
            • 2018-02-10
            • 1970-01-01
            • 2011-05-02
            • 2013-07-29
            • 2018-11-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多