Java基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long
这四种包装类默认创建了数值[-128,127]的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean直接返回true或者false。超出此范围会创建新的对象。
public static Boolean vatue0f(boolean b){
return(b?TRUE:FALSE);
}
private static class CharacterCache{
private CharacterCache(){}
static final Character cache[]=new Character[127+1];
static{
for(int i=0;i<cache.Length;i++)
cache[i]=new Character((char)i);
}
}
浮点类型的包装类Float和Double没有实现常量池技术
缓存区间设置为[-128,127]的原因:
由于Integer变量是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(在堆内存地址不同)。
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(非new生成的 Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer b = new Integer(100);
Integer c=100;
System.out.println(b == c); // false
对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则为true,如果不在这区间,则为false
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
因为当值在 -128 ~ 127之间时,java会进行自动装箱,然后会对值进行缓存,如果有相同的值,会直接在缓存中取出使用。缓存是通过Integer的内部类IntegerCache来完成的。当值超出此范围,会在堆中 new出一个对象来存储。
给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,
Integer i=30;在编译的时候会直接将30封装为Integer。
i=Integer.valueOf(30);会使用常量池中的对象。
源码:
public static Integer valueOf(String s, int radix) throws NumberFormatException
{
return Integer.valueOf(parseInt(s,radix));
}
/**
* (1)在-128~127之内:静态常量池中cache数组是static final类型,该对象会被存储于静
态常量池中。
* cache数组里面的元素不是static final类型,而是cache[k] = new Integer(j++),
* 这些元素是存储于堆中,只是cache数组对象存储的是堆中的Integer对象的地址
*
* (2)在-128~127 之外:在堆中新建一个 Integer对象,并返回。
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high) {
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
IntegerCache是Integer的内部类,源码:
/**
* 缓存支持自动装箱的对象标识语义 -128和127(含)。
* 缓存在第一次使用时初始化。 缓存的大小可以由-XX:AutoBoxCacheMax = <size>选项控制。
* 在VM初始化期间,java.lang.Integer.IntegerCache.high属性可以设置并保存在私有系统
属性中
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++) {
cache[k] = new Integer(j++); // 创建一个对象
}
}
private IntegerCache() {}
}
最大边界可以通过-XX:AutoBoxCacheMax进行配置
Integer a=newInteger(48);
Integer b=newInteger(48);
Integer c=newInteger(0);
System.out.println("a=b+c"+(a==b+c));
由于+不适用于Integer对象,所以b,c会先自动拆箱进行数值相加,又由于Integer对象无法与数值直接比较,所以a自动拆箱为int,最终转为48==48