一、new String都是在堆上创建字符串对象。当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用。
二、通过字面量赋值创建字符串(如:String str=”twm”)时, 会先在常量池中查找是否存在相同的字符串,( jdk 1.8 中 )若存在直接返回常量池引用;若不存在,直接将此常量添加到常量池,并且返回此常量(将栈中的引用指向该字符串)。
三、常量字符串的“+”操作,直接使用双引号常量和new String对象的区别
* 直接双:String str=”ja”+“va!";
1)直接组合成一个常量“java!”保存到常量池
2) 生成两个常量"ja" 和 "va"到常量池,生成一个对象"java"到堆空间
* new String: String str=new String("ja")+new String("va");
* 加号连接会添加三个对象到堆(两个new的和合并后的new的)和一个或者两个常量到常量池(两个是因为加号前后的内容不一致)
* 直双加newString:String str="ja"+new String("va");
* 加号连接会保存2个对象到堆(一个是new的一个是new+直双后的)。保存一个或者两个常量到常量池(内容不一致两个)
四、对于final字段,编译期直接进行了常量替换(而对于非final字段则是在运行期进行赋值处理的)。
final String str1=”ja”;
final String str2=”va”;
String str3=str1+str2;
在编译时,直接替换成了String str3=”ja”+”va”,根据第三条规则,再次替换成String str3=”JAVA”
五、常量字符串和变量拼接时(如:String str3=baseStr + “01”;)会调用stringBuilder.append()在堆上创建新的对象。
String aa = "AA";//设置常量AA到常量池
String bb = "BB";//设置常量BB到常量池
String ccdd = "CC"+"DD";//设置常量CCDD到常量池
String neeff = new String("EE")+new String("FF");//设置EE和FF到常量池。并且添加EE、FF和EEFF对象到堆
String aabb = aa+bb;//添加AABB对象到堆
String gghh = "GG"+new String("HH");//设置GG和HH常量到常量池,设置HH和GGHH对象到堆
// aa.intern();//啥事都不做,返回AA常量
// ccdd.intern();//啥事都不做,返回CCDD常量
// neeff.intern();//添加EEFF对象的引用到常量池,并返回EEFF对象
// aabb.intern();//添加AABB对象的引用到常量池,并返回AABB对象
// gghh.intern();//添加GGHH对象的引用到常量池,并返回GGHH对象