在Java中使用==运算符来比较包装器对象

时间:2012-04-14 00:28:05

标签: java integer wrapper equals operator-keyword

我正在阅读Kathy Sierra和Bert Bates的SCJP Java 6,这本书让我很困惑。在页245上,他们说明以下代码。

Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2)
System.out.println("different objects");

//Prints output
different objects

然后在下一页上,他们有以下代码

Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4)
System.out.println("same objects");

//Prints output
same objects

我很困惑!当我自己尝试这个时,似乎你不能使用==来比较你使用equals()方法的方式。即使整数变量设置为相同的值(即10),使用==总是给我'假'。我对么?使用==来比较相同的Integer对象(具有相同的值)将始终导致'false'

8 个答案:

答案 0 :(得分:59)

答案的关键是 object interning 。 Java实习小数(小于128),因此在实习范围内Integer(n)n的所有实例都是相同的。大于或等于128的数字未被实现,因此Integer(1000)个对象彼此不相等。

答案 1 :(得分:17)

如果查看Integer的源代码,您会看到Integer.valueOf(int) 所有值-128到127.原因是使用了小的整数值经常,因此值得汇集/缓存。

直接从Integer.java

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

请注意,此池是特定于实现的,并且无法保证池化范围。

关于实习的答案在概念上是正确的,但在术语上是错误的。在Java中实习通常意味着Java运行时正在执行池化(例如String的实习生)。在Integer的情况下,它是正在进行池化的类本身。没有JVM魔法。

答案 2 :(得分:7)

关于实习的上述答案是正确的。如果你这样做,可以考虑一些事情:

Integer i3 = new Integer(10);
Integer i4 = new Integer(10);

由于您明确地创建了新对象,因此您将不会拥有新对象。如果你按如下方式编写代码,它将被实习:

Integer i3 = Integer.valueOf(10);
Integer i4 = Integer.valueOf(10);

他们现在将再次成为同一个对象。如果您查看src.zip文件中Integer.java类中的valueOf方法,您可以看到它检查的位置,以查看int的值是否在-128到127之外,它会调用新的Integer类。它从缓存中加载它。

答案 3 :(得分:2)

Integer i1 = 1000;
Integer i2 = 1000;

编译器将int 1000作为Integer对象''。为此,它将源转换为以下内容:

Integer i1 = Integer.valueOf(1000);
Integer i2 = Integer.valueOf(1000);

现在valueOf可以是对new Integer(1000)的简单调用,但每次int装箱时创建一个新的Integer对象会耗费时间和空间。为了避免这种情况,Integer类为有限范围的int值保留一个Integer对象数组。

if(value> maxRange || value< minRange){
     //not in pool return new Integer
     return new Integer(value);
}else{
     //return pooled Integer object
     //for the value, pool contains all Integer
     //values from minRange to maxRange
     return integerPool[value-minRange];
}

通过在程序启动时使用jvm参数设置范围,可以调整获得的速度与丢失的内存之间的差异(默认情况下,默认为-127到128)。

答案 4 :(得分:0)

当Java ==运算符用于比较基本类型以外的任何内容时,它会检查引用相等性;即使被比较的东西是包裹的原语,这也适用。此外,valueOf方法和编译器生成的自动装箱语句通常可以随意返回一个新对象,该对象不会被引用 - 等于任何其他先前存在的引用,或者返回对现有对象的引用(当然,它将被引用 - 等于标识同一对象的任何预先存在的引用。需要实现来维护Integer实例的“池”值-128到127,这样对该范围内任何特定数字的Integer.valueOf的所有调用都将返回对同一对象的引用,但其他实现可以自由地执行类似

的操作
static Integer [] intPool = new Integer[256];

public Integer valueOf(int n)
{
  int hash = (n*0x18675309) >>> 24;
  Integer instance = intPool[n];
  if (instance == null && instance.value != n)
  {
    instance = new Integer(n);
    intPool[hash] = instance ;
  }
  return instance;
}

我并不特别希望Java实现能够做到这一点,因为在许多情况下,“缓存命中”比率可能接近0%,并且在缓存中查找实例所花费的额外时间将被浪费掉。尽管如此,从来没有任何保证instanceOf返回的引用与该方法返回的某个先前引用不匹配(即使它与该方法返回的 last 引用不匹配) ,一些缓存算法可能会导致它返回之前的引用,特别是如果池没有锁定而被多个线程共享。缺少锁定将永远不会导致代码返回除引用之外的任何内容一个具有正确值的整数,但可能导致不可预测的变化,其中返回的引用比较相等)。仅使用构造函数Integer直接创建的new Integer(n)对象的引用保证是唯一的;期望valueOf返回的任何引用与valueOf返回的任何引用不匹配但未实际发现它不匹配的代码应被视为已损坏。

答案 5 :(得分:0)

使用==和!=的字符串比较和整数比较给出的布尔结果不如我们所期望的那样。所以要小心并确保可能的未知结果不会妨碍软件的性能,可靠性和准确性。

答案 6 :(得分:0)

&#34; ==&#34;始终比较值的内存位置或对象引用。 equals方法总是比较values.but equals也间接使用&#34; ==&#34;运算符来比较值。整数使用整数缓存来存储-128到+ 127之间的值。如果==运算符用于检查-128到127之间的任何值,则返回true。如果-128到127之间的任何值为

Integer i1 = 1000;
Integer i2 = 1000;
System.out.println(i1 == i2); // returns false

除上述范围外,它返回false

JSONObject

Refer the link了解更多信息

答案 7 :(得分:0)

根据jls-5.1.7

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f,   
or an int or short number between -128 and 127 (inclusive), then let r1 and r2 
be the results of any two boxing conversions of p. It is always the case that r1 == r2.

因此,Interger类会缓存 -128 127 之间的任何数字。
请记住,在比较两个对象时,请始终使用equals方法。

缓存代码编写在IntegerCache类中,该类是Integer类的成员。

以下是代码段:

 /**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

参考