在Java中使用==操作符来比较包装对象在Java中使用==操作符来比较包装对象(Using ==

2019-05-13 12:17发布

我被凯西塞拉利昂和Bert贝茨读取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

我很困惑! 当我尝试了这一点,我自己看来,你不能使用==你会用等于同样的方式()方法进行比较。 使用==总是给我“假”即使整型变量设置为相同的值(即10)。 我对么? 使用==来比较相同的整数对象(同一值)总是会导致“假”

Answer 1:

答案的关键在于所谓的对象实习 。 爪哇实习生小数目(小于128),因此,所有的实例Integer(n)n在实习范围是相同的。 数大于或等于128不实习,因此Integer(1000)对象不彼此相等。



Answer 2:

如果你看一下源代码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的实习)。 在整数的情况下,它是做池类本身。 有没有JVM魔法参与。



Answer 3:

关于实习以上的答案是正确的。 如果你要考虑的事情,但:

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

你会不会有新的对象,因为你已经创建新对象显式。 如果你写的代码如下它将被拘禁:

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

现在他们将再次同一个对象。 如果你看一看的valueOf方法一样在src.zip文件中Integer.java类里面你可以看到,它检查看是否整型值是-128以外的127,它调用新的Integer类,否则它从缓存中加载它。



Answer 4:

Integer i1 = 1000;
Integer i2 = 1000;

编译器“方框”整型1000作为整数对象。 要做到这一点,输入源转换成如下:

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

现在valueOf可能是一个简单的调用new Integer(1000)但每次的时间来创建一个新的Integer对象int是盒装要花费时间和空间。 为了避免这种情况Integer类保持整数对象数组对于int值的有限范围。

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];
}

获得与丢失该存储器中的速度可以通过在程序开始(AFAIK默认为-127至128)设定的范围内与JVM参数进行调整。



Answer 5:

当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不匹配此方法(即使它不通过该方法返回的最后一个参考匹配回到以前的一些参考,一些缓存算法有可能会导致它返回一个参考,特别是在游泳池被多个线程没有锁定共享。缺乏锁定绝不会导致代码返回其他任何东西,而不是正确的值的整数的引用,但可能会导致在返回引用比较平等的不可预测的变化)。 仅参考Integer使用构造直接创建的对象new Integer(n)保证是唯一的; 其预期在返回的任何参考码valueOf不匹配由返回的任何参考valueOf具有实际观察到的,没有它不匹配,应考虑破碎。



Answer 6:

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



Answer 7:

“==”总是比较存储器位置或对象中的引用。 equals方法总是比较values.but也等于间接地使用“==”操作符来比较值。 整数使用整数高速缓存中的值-128存储+ 127.If ==操作符是用来之间-128到127,然后返回true检查任何价值。 如果-128之间的任何值到127

Integer i1 = -128; 
Integer i2 = -128; 
System.out.println(i1 == i2); // returns true

超过上述范围的其他则返回假

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

请参阅链接的一些附加信息



Answer 8:

根据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.

因此,-128127之间的任意数字是基于整数级缓存。
请记住,比较两个对象时总是使用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() {}
}

参考

  • JLS-5.1.7
  • Integer类代码
  • 整数Java文档


文章来源: Using == operator in Java to compare wrapper objects