Java中整数常量池的概念:
java中为了提高程序的执行效率,将[-128, 127]之间256个整数所有的包装对象提前创建好了,类加载时就已经创好了,放在了一个方法区的“整数常量池”当中。
目的是:如果一个整数范围在[-128, 127]里面的整数进行包装,包装时不需要再new对象了,直接从“整数常量池”中取出来。
池:就是缓存区的意思。缓存区的好处是:程序用起来执行很快,很方便。缺点是:如果没用到,就有点耗费了内存。
翻阅Integer的源代码,发现有一个私有静态内部类IntegerCache。
这个IntegerCache类中,有一个static final修饰的常量数组,不可改变的,名叫Integer[] cache。
这个cache数组保存了[-128, 127]所有整数的包装类地址,存在方法区的整数常量池当中。
测试代码:
public class Test06 {
public static void main(String[] args) {
//我们再来看一段很有意思的代码,猜想一下为什么
Integer a1 = 127;
Integer a2 = 127;
System.out.println(a1 == a2); //true
Integer b1 = 128;
Integer b2 = 128;
System.out.println(b1 == b2); //false
//大胆预测Integer的一些对象应该跟byte的范围有关,确实如此
//整数127的包装类和127的包装类地址是一样的,128就不一样了
//我们继续测试一下负整数的范围
Integer c1 = -129;
Integer c2 = -129;
System.out.println(c1 == c2); //false
Integer d1 = -128;
Integer d2 = -128;
System.out.println(d1 == d2); //true
//所以说[-128, 127]之间整数的包装对象的地址已经创建好了,不会再new了,直接指向“整数常量池”中对应数字的地址
//再来测试一下强制使用new会怎么样
Integer e1 = 127;
Integer e2 = new Integer(127);
System.out.println(e1 == e2); // false
/*
* 分析:e1保存的是整数常量池中127包装类的地址
* e2保存的是堆中对象的地址,堆中对象发现数字是127,不会保存127数据,而是保存整数常量池127包装类的地址
* */
}
}
总结:
范围在[-128, 127]内的整数,装箱成包装类时,底层不会new对象。共用在整数常量池当中的256个Integer对象。
例如:
Integer a = -128;
Integer b = -128;
则a和b指向整数常量池中的同一个对象。