Java基础之包装类的自动装箱、拆箱和Integer的值缓存范围

引入包装类的原因

Java是纯面向对象语言,“EverythingIs an Object”是它的主要特点。但是考虑到程序运行效率和日常编程习惯,java还是引入不是对象的基本数据类型(primitive types)。然而,像Vector,HashMap,ArrayList等集合类的元素必须是对象类型,使用基本类型不符合要求。因此,java为每一个基本数据类型都提供了对应的包装类型(wrapper class)。JDK 1.5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

 原始类型(primitive types):boolean, byte, char, short, int, long, float, double

包装类型(wrapper class)  :Boolean, Byte, Character, Short, Integer, Long, Float, Double

自动装箱、拆箱

基本类型变为包装类的过程称为装箱,将包装类变为基本数据类型的过程称为拆箱。

当我们直接给一个Integer对象赋一个int值的时候,会调用Integer类中的静态方法valueOf(int i)。

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

反之,当我们把一个Integer对象赋值给一个int类型时,会自动调用Integer类中的intValue()方法。

/**
 * Returns the value of this {@code Integer} as an
 * {@code int}.
 */
public int intValue() {
    return value;
}
Integer的值缓存范围

讲Integer类,就不得不提一个比较让人困惑的问题,先看下面的代码:

public class Test {
	public static void main(String[] args) {
		Integer i1 = 100;
		Integer i2 = 100;
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i1 == i2); 	//true
		System.out.println(i3 == i4); 	//false
        }
}

如果不明白就很容易认为两个输出都是true,而实际运行结果是第一个true第二个false。首先因为i1, i2, i3, i4这四个变量是Integer对象,所以==运算比较的是引用而不是值了。也就是说i1和i2指向的对象是相同的,i3和i4指向的对象是不同的。这就得知道Integer的值缓存范围了。

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

        static {
            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);                   
                    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() {}
    }

上面源码得知,字面量值范围在-128到127之间。前面提到当我们给Integer对象赋int值时会调用静态方法valueOf()。如果字面量的值在-128到127之间,那么不会new一个新的Integer对象,而是直接引用常量池里面的Integer对象,所以上面的i1 == i2返回结果为true。而i3和i4超出缓存范围,要分别new一个新的Integer对象,所以i3 == i4返回false。



你可能感兴趣的:(Java基础之包装类的自动装箱、拆箱和Integer的值缓存范围)