最近看尚硅谷2020最新版宋红康JVM教程更新至中篇(java虚拟机详解,jvm从入门到精通)视频,解决了部分java String方面的疑惑,在此做个笔记。

##0. Sting a = s.intern() 之intern()方法
从字符串常量池中查询是否存在字符串“s”。

存在,则将此地址指向a
不存在,则:

  • jdk1.6中:在常量池中new出该字符串(“s”),并将其指向a
  • jdk1.7及以上中:堆空间中有“s”,则在常量池中创建指向堆空间中s的引用;否则,在常量池中new出该字符串(“s”),并将其指向a(同上)。
JDK1.6情况.png *jdk1.6之前的常量池不在堆中,在方法区中,故而画在外面。 JDK1.7及以上情况

##1. String a = “ab”
“ab”直接存到了常量池中。
String a = "ab"示意图

##2. String a = new String(“ab”)
实质上new了两个对象:1.new了个String类型的对象,放在堆中;2.常量池中放入“ab”。 证据请看编译后的字节码(第一行和第三行):

1
2
3
4
5
6
 0 new #2 <java/lang/String>
3 dup
4 ldc #3 <ab>
6 invokespecial #4 <java/lang/String.<init>>
9 astore_1
10 return

证明常量池中有“ab”。
String a = new String("ab")示意图

因此 "ab" == new String("ab")为 false

##3. String a = new String(“a”)+new String(“b”)

字符串中的加号“+”本质操作为StringBuild.append().toString()操作

所以,此处先String了”a”,后String了”b”。再通过StringBuild.append().toString()操作new出了对象“ab”,放在了堆中。常量池中仅有“a”和“b”,并没有“ab”。
String a = new String("a")+new String("b")示意图

现在再去看康老师讲的几道题目解析就很清晰了:

题目1

题目1.png

JDK1.6情况 JDK1.7及以上情况

题目2

1
2
3
4
5
6
public static void main(String[] args) {
String s = new String("ab");
s.intern();
String s2 = "ab";
System.out.println(s == s2);//jdk1.6/1.7以上:答案均为 false
}

①new String(“ab”)在堆和常量池中均创建了“ab”,②intern直接创建常量池中的“ab”;③s2指向常量池中的“ab”。应该可以仿照上面画图进行解释了。