
- 常量池是 .class文件,存放堆中数据的引用地址,而不是真实的对象,运行时常量池是jvm运行时将常量池中数据放入池中,此时引用地址真正的指向对象而不是.class文件;Stringtable是哈希表(不能扩容),它也叫做串池,用来存储字符串,这3个不是同一个东西,我们需要进行区分
- String table中存储的并不是String类型的对象,存储的而是指向String对象的索引,真实对象还是存储在堆中
- jdk1.6中,Stringtable是放在永久代(方法区)中,jvm进行FullGC才会对常量池进行垃圾回收,影响效率,因此在jdk1.8中将Stringtable放在堆中,jvm内存紧张时就会对Stringtable进行垃圾回收
StringTable 特性
- 常量池中的字符串仅是符号,第一次用到时才变为对象
- 利用串池的机制,来避免重复创建字符串对象
- 字符串变量拼接的原理是StringBuilder (1.8)
- 字符串常量拼接的原理是编译期优化 可以使用 intern方法,主动将串池中还没有的字符串对象放入串池
- jdk1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串 池中的对象返回
- jdk1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份 (此时原对象还是指向原对象而不是池中的返回的对象), 放入串池, 会把串池中的对象返回
jvm参数设置
-XX:StringTableSize=桶个数
常见面试题
public static void main(String[] args) {
String str1 = "abc";
//编译期间对其优化,实际待放入池中的数据就是“abc” , 此时池中已有该数据 ,则返回str1放入池中的“abc”的引用
String str2 = "ab" + "c";
//new出来的对象都是在堆中,因此str3和str1地址不同
String str3 = new String("ab") + "c";
//入池,已存在,返回池中对象
String str4 = str3.intern();
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
System.out.println(str1 == str4); // true
}
参考资料:
https://blog.csdn.net/gw_9527/article/details/103002455
https://blog.csdn.net/Liyuehahaha/article/details/102547755
版权声明:本文为shuaigeyimei1原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。