1.String的基本特性
String的String Pool是一个固定大小的Hashtable,默认值大小是长度是1009.如果放进String Pool的String 非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表很长的直接影响是调用String.intern时性能会大幅下降;
使用-XX:StringTableSize可以设置StringTable的长度
在JDK6中StringTable时固定的,就是1009的长度,所以常量池的字符串过多,就会导致效率下降很快,StringTableSize设置没有要求;
在JDK7中,StringTable的长度默认值是60013,StringTableSize设置没有要求;
在JDK8中,设置StringTable的长度,1009是可设置的最小值;
2.使用String类型常量池的方式
1.使用双引号方式声明对象:String str =“String”;
2.使用String类提供的intern()方法
3.不同JDK版本String常量池的存放位置
1.JDK6及以前,String常量池存放在永久代上;
2.JDK7后,字符串常量池调整存放在Java堆内;
所有的字符串都保存在堆中,和其他普通对象一样,在进行调优应用时仅需要调整堆的大小就可以了;
4.字符串拼接操作
1.常量与常量的拼接结果放在常量池当中, 原理是编译器优化
2.常量池不会存在相同内容的常量
3.只要其中有一个时变量,结果就在堆中相当于new了一个对象。变量拼接的原理是StringBuilder
4.如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象 地址
public void test(){ String s1 = "javaEE"; String s2 = "hadoop"; String s3 = "javaEEhadoop"; String s4 = "javaEE" + "hadoop";//编译期优化 //如果拼接符号的前后出现了变量,则相当于在堆空间中new String(),具体的内容为拼接的结果:javaEEhadoop String s5 = s1 + "hadoop"; String s6 = "javaEE" + s2; String s7 = s1 + s2; System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false System.out.println(s3 == s6);//false System.out.println(s3 == s7);//false System.out.println(s5 == s6);//false System.out.println(s5 == s7);//false System.out.println(s6 == s7);//false //intern():判断字符串常量池中是否存在javaEEhadoop值,如果存在,则返回常量池中javaEEhadoop的地址; //如果字符串常量池中不存在javaEEhadoop,则在常量池中加载一份javaEEhadoop,并返回次对象的地址。 String s8 = s6.intern(); System.out.println(s3 == s8);//true }
5.字符串拼接的底层实现不一定使用StringBuilder,当符号拼接左右两边为字符串常量或常量引用,会在编译期优化
public void test1(){ final String s1 = "a"; final String s2 = "b"; String s3 = "ab"; String s4 = s1 + s2; System.out.println(s3 == s4);//true }
6.StringBuilder使用优化:在基本确定字符串长度时,尽量初始化一个对应大小的初始容量值,避免扩容造成性能消耗