8

考虑这段代码:

class test {
   public static void main(String[] args) {
      test inst_test = new test();
      int i1 = 2000;
      int i2 = 2000;
      int i3 = 2;
      int i4 = 2;
      Integer Ithree = new Integer(2); // 1
      Integer Ifour = new Integer(2); // 2
      System.out.println( Ithree == Ifour );
      inst_test.method( i3 , i4 );
      inst_test.method( i1 , i2 );
   }
   public void method( Integer i , Integer eye ) {
      System.out.println(i == eye );
   }
}

它打印:

false
true
false

我理解第一个false, == 运算符只检查两个引用是否在同一个对象上工作,在这种情况下不是。

以下内容让我摸不着头脑truefalse为什么Java会考虑和i3平等i4但又不同?两者都被包装成整数,不应该评估为假吗?这种不一致是否有实际原因?i1i2

4

7 回答 7

15

将原语自动装箱到对象中(如在调用中method使用的使用小值缓存。来自Java 语言规范第 5.1.7 节

如果被装箱的值 p 是真、假、一个字节、一个在 \u0000 到 \u007f 范围内的字符,或者一个介于 -128 和 127 之间的 int 或短数字,则令 r1 和 r2 为任意两次装箱转换的结果p。r1 == r2 总是如此。

紧随其后的规范的讨论部分也很有趣。值得注意的是,如果 JVM 愿意,它可以缓存更多的值——你不能确定这样做的结果:

Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
于 2009-07-18T22:58:32.127 回答
7

自动装箱时,缓存 -128 和 127 之间的整数,并返回相同的包装对象。与 \u0000 和 \u007F 之间的布尔值和字符值相同

这是你大部分时间得到的,但它取决于 JVM 实现。

于 2009-07-18T22:57:48.587 回答
2

这是因为装箱使低于某个值(我认为是 128)的整数指代一些预先构造的对象,而更高的值则指代新对象。

于 2009-07-18T22:55:30.700 回答
1

自动装箱使用Integer.valueOf(i)而非 new Integer(i) 来构造 Integer 类的对象。

正如其他人所说, valueOf() 使用缓存,主要是为了空间效率。

不要在引用类型上使用 ==,这几乎总是一个错误。

于 2009-07-19T06:55:40.890 回答
0

我猜想包装试图最小化整数对象的数量并且只创建一个代表 2 的对象也节省内存。

只要记住永远不要在你永远不知道会发生什么的对象上使用 == 。

于 2009-07-18T22:57:51.350 回答
0

Integer 类包含一些常用实例的缓存。值的范围通常因 JVM 而异(有时也是可配置的),但通常相关代码类似于:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

(来自 sun JDK 1.6 的代码)

这就像字符串实习,因为它既节省内存又允许使用引用测试相等(例如==代替equals

于 2009-07-18T23:00:10.237 回答
0

自动装箱使用一些缓存机制。通常你不应该依赖==,总是使用equals来检查相等性。

于 2010-01-28T11:23:31.153 回答