package design.wlb.studyjava.demo.restudy.c4jvm专题.chapter02.c29StringTable_字符串变量拼接;
public class Client {
//StringTable["a","b","ab"](懒加载)
public static void main(String[] args) {
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2; //由javap反编译可知,它是new了StringBuilder对象,再执行了toString()方法【 return new String(value, 0, count);】,创建了一个新的字符串对象
System.out.println(s4==s3);
}
/**
* 9: new #5 // class java/lang/StringBuilder
* 12: dup
* 13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
* 16: aload_1
* 17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
* 20: aload_2
* 21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
* 24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
*/
}
我们来看上面这段代码,s4 == s3 最后会输出什么结果?
答案是:false ,为什么呢?
通过javap命令反编译可知,s1 + s2 ,jvm对其做的操作是,使用StringBuilder将其两个字符串进行一个拼接,最后通过toString的方法得到一个字符串对象,因为toString里面的方法实现是return new String(value,0,count);它是通过new关键字创建的ab,这个存在与“非串池的堆中”。
在前面17章里面,我们知道在通过new 关键字创建的对象都在堆中。
在前面22章里面,我们知道了在jdk1.6中,StringTable串池在常量池在方法区中,jdk1.8中,常量池在元空间不归jvm管理,但串池不在常量池中,是在堆中。
当然jdk1.6方法区逻辑上是在堆里面,jdk 1.8方法区在元空间,但串池在堆里。
串池和普通的堆对象存的东西不一样。一个是存字符串常量,另一个存java对象的地址引用。当然字符串对象可以调用intern()方法,将其存入串池中。这个后面有所讲解。
好,这里就先讲到这。