1.介绍
关于Integer和int在面试的时候出现的频率很高。而我们所熟知的是Integer是int 的包装类型,int的初始值为0,Integer的初始值为null,这是基本都知道的。至于Integer的自动装箱和拆箱,以及Integer的缓存等小细节需要深入思考。
2.包装类的装箱和拆箱
从基本数据类型到包装类型的过程是装箱、从包装类型到基本数据类型的过程是拆箱。
例子:
public static void main(String[] args) { //标准的装箱过程 Integer i =new Integer(127); /** * 这个写法相当于Integer i1 =new Integer(127); * 这个初始化的过程默认也是使用了自动装箱 * 装箱的本意就是将基本数据类型转换成包装类型 * */ Integer i1 =127; //标准的拆箱过程 int j =i.intValue(); /** * 这个写法相当于int j1 =i1.intValue(); * 这个初始化的过程默认也是使用了自动拆箱过程 * 拆箱的本意就是将包装类型转换成基本数据类型 * */ int j1 =i1; }
int(4字节) | Integer |
byte(1字节) | Byte |
short(2字节) | Short |
long(8字节) | Long |
float(4字节) | Float |
double(8字节) | Double |
char(2字节) | Character |
boolean(未定) | Boolean |
3.Integer的缓存
Integer定义了一个静态内部类IntegerCache作为缓存
缓存源码:
-
private static class IntegerCache {
-
//常量最小值-128
-
static final int low = -128;
-
//常量最大值
-
static final int high;
-
//Integer缓存数组
-
static final Integer cache[];
-
-
static {
-
//初始化h变量为127
-
int h = 127;
-
String integerCacheHighPropValue =
-
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
-
if (integerCacheHighPropValue != null) {
-
int i = parseInt(integerCacheHighPropValue);
-
//说明i最小可以取到127,规定了i的下限,所以i>=127
-
i = Math.max(i, 127);
-
//由于i>=127并且Integer.MAX_VALUE - (-low)>128,因此可以得到h>=127
-
h = Math.min(i, Integer.MAX_VALUE - (-low));
-
}
-
high = h;
-
//初始化Integer缓存数组
-
cache = new Integer[(high - low) + 1];
-
//数组中的初始值是-128
-
int j = low;
-
//循环为数组赋值,数组0位是-128,最大是127(临界值)
-
for(int k = 0; k
< cache.length; k++)
-
cache[k] = new Integer(j++);
-
}
-
-
private IntegerCache() {}
-
}
-
-
/**
-
* 返回一个表示指定的 int 值的 Integer 实例。
-
* 如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int)
-
* 因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能
-
*/
-
public static Integer valueOf(int i) {
-
assert IntegerCache.high >= 127;
-
//当-128
<=i<=127时,直接从缓存数组中取出值
-
if (
i >= IntegerCache.low && i
<= IntegerCache.high)
-
return IntegerCache.cache[i + (-IntegerCache.low)];
-
//否则返回新的Integer对象
-
return new Integer(i);
-
}
-
而我们使用Integer i=100的时候采取的装箱操作实际上调用了valueof方法,API也提示尽量多使用valueof的方式创建Integer的实例而不是以new Integer的方式。因为valueof方式使用缓存提高空间的利用率和时间性能。
4.经典面试题
打印结果:
public static void main(String[] args) { //标准的装箱过程 Integer i =new Integer(100); Integer i1 =100; Integer i2 =100; Integer i3 =128; Integer i4 =128; System.out.println("i==i1 :"+(i==i1)); System.out.println("i1==i2 :"+(i1==i2)); System.out.println("i3==i4 :"+(i3==i4)); }
解释:
(1) i == i1 :由于i本身是new Integer的方式单独开辟空间,i1是 -128<=i1<=127,所以i1是从缓存中取出数据的。而缓存的地址和new Integer单独开辟空间对应的地址不同,返回false。
(2) i1 == i2 :i1是 -128<=i1<=127,所以i1是从缓存中取出数据的。i2是-128<=i2<=127,所以i2也是从缓存中取出数据的。所以i1和i2对应的是同一个缓存地址,返回true。
(3)i3 == i4 :i3>127并且i4>127,所以i3和i4分别是new Integer这种单独开辟空间,地址不同,返回false。