java Integer/Long等比较须知


在java编程中,自动装箱和拆箱,相信大家都不陌生,但是在比较过程中,会有一些坑,尤其是业务代码复杂的时候,比较容易掉进去。今天就说一下,我遇到的一个基本类型比较的问题。

WrapperClass缓存

在基本类型的wrapperClass中,有些是有缓存的,比如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() {}
}

以上为Integer的缓存,可以看到对于-128到127的Integer在java运行的时候已经作为trust类被加载到jvm中,当然他的IntegerCache类也被初始化完成。

valueOf&intValue

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

这是自动装箱的使用方法,大家可以自己编写一个自动装箱的测试代码,然后通过javap -c命令查看的反编译代码。看到装箱的过程中,使用了IntegerCache中缓存好的Integer。

public int intValue() {
    return value;
}

自动拆箱方法

new

Integer的new方法和其他对象没什么区别。肯定需要开辟新的对象空间。一个新的对象。

小结

通过以上,我们可以看到Integer的装箱和拆箱的原理,然后我们平时使用到的比较的时候就需要注意。

  1. 如果都是通过自动装箱获得的Integer,如果都在[-127,128]中,那么直接对比的是cache中的对象的引用,也可以间接的达到比较值的作用。
  2. 如果Integer的值在[-127,128]这个范围外部,那么执行new Integer(i)方法,创建新的对象。==号的作用,失去了间接比对的作用。

综上所述:如果碰到了WrapperClass比较的情况,直接使用CompareTo方法比较。使用==虽然在小值可以间接达到自己的目的,但是很容易掉进这个坑。排查比较困难。

当然除了Integer还有其他的WrapperClass也使用了Cache,如下:

类型 cache范围
Byte [-128,127]
Short [-128,127]
Integer [-128,127]
Long [-128,127]
Boolean true,false
Character [0,127]
Double 无cache
Float 无cache

猜你喜欢

转载自blog.csdn.net/weixin_37924923/article/details/85048413