String 的String pool (字符串常量池)是一个固定大小的HashTable,jdk6 中是默认的数组长度是1009
如果放入String pool 中的String太多,会造成hash冲突严重,导致链表很长,链表长了对于数据的更新和读取都是有性能的下降 可以通过-XX:StringTableSize参数设置大小
jdk8 开始默认的StringTable的长度是60013,1009是可设置的最小值,如果设置的值小于这个值是不允许的
java语言有8中基本类型和一种比较特殊的类型String,这些类型为了使他们在运行中更快都提供了常量池的概念,常量池类似于java系统级别提供的缓存
直接通过双引号声明出来的String对象会直接存储在常量池中,称为字符串字面量
不是通过双引号声明的String对象可以使用String提供的intern方法往常量池中放入字符串
在java6中,字符串常量池是存储在永久代中
在java7中,常量池的位置调整到java堆中
java8调整概念为元空间,字符串常量在堆中
为什么调整
1)permSize默认比较小 2)永久代GC回收频率低
关于字符串拼接
1.字符串拼接字符串的结果是放在常量池中,原理是编译期优化
String s1 = "a"+"b"+"c";
String s2 = "abc";
s1 == s2 //true
2.如果拼接前后出现变量,则结果是在堆中,相当于在堆空间中new String()
String s1 = "a";
String s2 = "b";
String s3 = "ab;
String s4 = s1+s2;
s3==s4//false
String s4 = s1+s2的执行细节:
1)StringBUilder s = new StringBuilder;
2)s.append("a");
3)s.append("b");
4)s.toString
3.字符串拼接操作不一定使用StringBuilder,如果字符串前后都是字符串常量或者常量引用
则仍然适用编译期优化
final String s2 = "b";
final String s3 = "ab;
String s4 = s1+s2;
s3==s4//true
final修饰了s1 和s2,在编译期就确定了,可以理解为一个常量
4.intern方法判断字符串常量池中是否在字符串,如果存在,则返回常量池中的地址,如果不存在
则在常量池中放入,并返回常量池中存在该对象的地址