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类,就不得不提一个比较让人困惑的问题,先看下面的代码:
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。