文章目录
一、内存结构图
JDK1.6
JDK1.8
我们发现,StringTable
移入了Heap
里面。所以,应该想到,StringTable
将受到GC
管理。
其实,1.6
中,在方法区中的时候,也是受GC
管理的。
二、案例讲解
题目
java
public class Demo7 {
public static void main(String[] args) {
String s1 = "a";
String s2 = "b";
String s3="a" + "b";
String s4 = s1 + s2;
String s5 = "ab";
String s6 = s4.intern();
//问提
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
String x2 = new String("c") + new String("d");
String x1 = "cd";
x2.intern();
//问,如果调换了最后两行代码,如果是1.6,?
System.out.println(x1 == x2);
}
}
首先,我们要知道,==
号进行的比较,是比较引用的内存地址是否相同。
如果想要比较String
的内容,用equals
方法就可以。
字节码
主要看下红线处的几行代码
简单理解就是:
1、StringTable
是一个HashTable
结构(桶(数组)+链表
)
2、代码翻译
java
String s1 = "a";
String s2 = "b";
String s3="a" + "b";
String s4 = s1 + s2;
前三行代码可以简单的理解为,JVM
启动后,会创建一个StringTable
我现在简单点把StringTable
表示成StringTable[]
这样
于是
上面三行代码就是
StringTable [ "a", "b" ,"ab" ]
最后一行代码是
new StringBuilder().append("a").append("b").toString() new String("ab")
intern方法
就是将字符串主动放入StringTable
中,并返回StringTable
中的引用地址。
1.8和1.6的区别就是
1.8不在复制对象。所以,原来的引用指向会发生改变。
而1.6是复制对象,所以,原来的引用指向不会发生变化。
三、总结
常量池中的字符串仅仅是一个符号,第一次用到时,才会变成对象。
利用串池的机制,来避免重复创建字符串对象。
字符串变量
凭借的原理是StringBuilder(1.8)
字符串常量
凭借的原理是编译期优化
可以用intern
方法,主动将串池中没有的字符串对象放入串池中。
- 1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串
池中的对象引用返回 - 1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份,
放入串池, 会把串池中的对象引用返回
简单记忆
字符串的创建方式,如果是new
的方式,就是放入堆中,而不放入串池中。
如果是""
双引号方式创建,则是直接放入串池中。