以Integer为例分析装箱拆箱
拆箱与装箱是java面试题中常见题型,今天来分析一下拆箱与装箱以及对java基本数据类型进行复习
八大基本数据类型
基本类型 | 包装类 |
---|---|
short | Short |
int | Integer |
float | Float |
char | Character |
byte | Byte |
long | Long |
double | Double |
bool | Boolean |
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
先看到包装类Integer
public final class Integer extends Number
implements Comparable<Integer>, Constable, ConstantDesc
Integer继承Number类,实现了Comparable接口实现排序
- 首先看到**Integer.valueOf()**函数
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache是Interger类中的一个静态内部类,
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
Integer的缓存机制: Integer是对小数据(-128-127)是有缓存的,再jvm初始化的时候,在静态方法中调用VM.initializeFromArchive(IntegerCache.class),将数据-128-127之间的数字便被缓存到了本地内存中,如果初始化-128~127之间的数字,会直接从内存中取出,不需要新建一个对象,再赋值给cache
同样的缓存机制类型还有Short,Byte,Character,Long
注意点:
- Integer使用new的时候,一定创建的是一个新的对象
- Integer a = 126 ;这种情况下会自动装箱,把基本类型转换为包装类,会从缓存中获取对象;此时当我们使用Integer b = 126,在判断 a==b时候,因为两个对象是同一个对象,所以会返回true
- 但是如果使用Integer a = new Integer(126)的时候,这时候会在java堆中开辟一个新的对象,此时再调用==判断的时候就不是相同的对象了
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象,原因是他们都是浮点类型,在底层采用的存储方式是底数+指数的方式,因此可以说在某个区间内有无数个对象,无法使用缓存机制来存储,所以每次只能够创建一个新的对象