看一个例子
public class Test4 {
public static void main(String[] args) {
String s1 = "b";
String s2 = "a";
String s3 = s1 + "d";
String s4 = "e" + "f";
String s5 = s1 + s2;
}
}
问题是,现在字符串常量池里有哪些字符串常量?
显然“a” "b" "ef" 是存在的,“d”,"e" ,"f","ab",“bd” 存在么?
我们通过反编译来查看常量池情况。
可以得出结论:
1.俩个或多个字面量直接相加,是在编译期间进行的,只会将结果存放在字符串常量池。
2.一个字符串变量和一字面量相加时,常量池中会保存字面量,而不会保存生成的字符串对象。新的对象是被存在了堆中。为什么和第一点里的情况不一样,这里的字面量会被保存在常量池中?我的理解是因为第一点字符串相加的结果在编译期就可以确定,运行期间是不需要用到相加时的字面量的,所以不需要保存。而第二种情况,结果字符串因为有变量的存在,所以编译期不可知,需要在运行时计算生成,需要运行时用到字面量,所以常量池会保存它。同样,String s = new String("aaa"); 常量池也会保存“aaa”,因为运行期生成对象会用到这个“aaa”。
3.两个字符串变量相加时,与第二点类似,也是生成的新对象存储在堆上。
思考:如果第二点中的字符串变量是final类型修饰的,那么是什么结果?
其实final变量因为不可变性,所以是编译期可知的,所以如果上述例子中s1是final,那么字符串常量池中会多出一个“bd”,而少了“d”。