1. 常量池在内存中的位置:
2. 常量池的概念以及作用
首先,基本数据类型不会用到常量池,因为一般的运算、判断和赋值都是对值的操作,直接在虚拟机栈中进行,不涉及到对象,也就与堆内存无关(也就涉及不到对象的创建以及垃圾回收),不会对系统性能造成太大的影响。
// 在[-128,127]这个范围
Integer i1 = 40;
Integer i2 = 40;
System.out.println(i1==i2);//输出TRUE
// 不在上述范围
Integer i3 = 400;
Integer i4 = 400;
System.out.println(i3==i4); // false
Double i1=1.2;
Double i2=1.2;
System.out.println(i1==i2);//输出false
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println("i1=i2 " + (i1 == i2)); // true
System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); // true
System.out.println("i1=i4 " + (i1 == i4)); // false
System.out.println("i4=i5 " + (i4 == i5)); // false
// i4,i5,i6三个对象都自动拆箱为基本数据类型,不再是对象,而是数值之间的比较。
System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); // true
System.out.println("40=i5+i6 " + (40 == i5 + i6)); // true
1. 只有包含双引号" "指定的字符串 (都在pool中)
// 在编译期间就能确定"aa"这样一个字符串对象,所以是放到常量池中,但常量池中没有"a"
String str1 = "a" + "a";
2. 不全是双引号" "指定的字符串进行连接(不都在pool中)
String str1 = new String("b");
String str2 = "c" + str1; // 在编译期间不能确定,运行期间存到堆内存中
String str3 = new String("c");
String str4 = str1 + str3; // 在编译期间不能确定,运行期间存到堆内存中
System.out.println(str2==str4) // false 都在堆内存中,地址肯定不同
示例:final修饰的变量编译器已确定,对象存在常量池中
String s0 = "111"; //pool
String s1 = new String("111"); //heap
final String s2 = "111"; //pool 编译器已确定
String s3 = "sss111"; //pool
String s4 = "sss" + "111"; //pool
String s5 = "sss" + s0; //heap
String s6 = "sss" + s1; //heap
String s7 = "sss" + s2; //pool
String s8 = "sss" + s0; //heap
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //true
System.out.println(s5 == s6); //false
System.out.println(s5 == s8); //false
1. 编译期间可以创建的对象放在常量池中。
String str1 = "xyz";
Integer a = 1;
2. 运行期间用new创建的对象放在堆内存中。
String str1 = new String("aaa");
Integer a = new Integer(2);
3. 存放位置不同的两个对象对应的引用一定不相等。
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2); // false
4. 运行时常量池具有动态性,即运行期间也可以向常量池中添加新的常量。
// 动态性
// 常量池中本没有“abc”,程序执行以下语句时,会先在常量池中创建一个“abc”对象
// 然后把对象的引用(地址)返回给str1。此时str1的值是对象引用。
String str1 = "abc".intern();
// 常量池中已经有“xyz”对象了,那么无需创建,直接将对象返回给str3,此时str3的值是对象,而非引用。
String str2 = "xyz";
String str3 = str2.intern();
5. 如果指向的对象都在常量池,那么指向的一定是同一个对象,即str1=str2 (值相同,地址相同)
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); // true
6. 除了5以外的两种情况,两个对象引用的值都不相等。
// 情况1:一个在常量池中,一个在堆内存中
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2); // false
// 情况2:两个都在堆内存中
String str3 = new String("xyz");
String str4 = new String("xyz");
System.out.println(str3==str4); //false