基本类型和包装类型的区别是什么
存储方式:基本类型存储一般情况下储存在栈中(这里指的是局部变量),而基本类型的成员变量比如类的属性,会存储在堆之中。而包装类型我们都知道是引用类型存储在堆内存之中。
占用空间:基本类型要比包装类型要明显小。
默认值不同:包装类型不赋值默认值是null,而基本类型不赋值一般有默认值。
比较方式:基本类型==比较的是值,而包装类型比较的是对象的内存地址。
包装类型的缓存机制了解吗
Byte、Short、Integer、Long这4种包装类型默认创建了数值[-128,127]的相应类型的缓存数据,Character创建了数值在[0,127]的范围内的缓存数据。Boolean直接返回True或者False。
Integer缓存源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static final class IntegerCache {
static final int low = -128;
static final int high;
@Stable
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
CDS.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;
}
private IntegerCache() {}
}
其实,所谓的缓存也就是说当我们需要使用-128到127这些值的时候不需要再创建新的对象。这段代码之中的valueof就是我们常用的把int类型转换位Integer类型的静态方法,我们可以看到在Integer中定义了一个内部类IntegerCache,简单地说这个类缓存了一定范围内Integer对象在数组中,减少了我们创建新对象的消耗。
因此我们要注意当我们比较值在-128到127范围内的Integer时候,我们可以使用==来比较,因为他们在缓存中指向的地址相同。但是别的一定要equals来比较。
自动装箱和自动拆箱
装箱:将基本类型用他们对应的引用类型包装起来
拆箱:将包装类型转换位基本类型
Integer i = 10; //装箱
int n = i; //拆箱
对应的字节码文件
L1
LINENUMBER 8 L1
ALOAD 0
BIPUSH 10
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;
L2
LINENUMBER 9 L2
ALOAD 0
ALOAD 0
GETFIELD AutoBoxTest.i : Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
PUTFIELD AutoBoxTest.n : I
RETURN
可以看出装箱时候就是调用了valueof方法而拆箱时候则是调用了intvalue方法。
因此实际上
Integer i = 10 等价于 Integer i = Integer.valueOf(10)
int n = i 等价于 int n = i.intValue();
最后频繁拆装箱也会影响系统性能。