如果能做出来如下题目,这个内容就就没问题了
String s1=“a”; 1
String s2=“b”; 2
String s3=“a”+“b”; 3
String s4=s1+s2; 4
String s5=“ab”; 5
String s6=s4.intern(); 6
s3= =s4 ?
s3= = s5?
s3= =s6?
String p2=new String(“c”)+new String(“d”); 7
p3=p2.intern();
String p1=“cd”; 8
System.out.println(p1p2);?
常量被加载到运行常量池,此时并不会变成字符串对象,只有执行String s1="a"才成为对象(相当于延迟加载),成为对象后放到StringTable[]中作为key(StringTable是一个hash表,初始为空)。执行完第1行后"a"放入StirngTable中。
第2行 String s2=“b”; 同理
第3行 这步会先进行a,b的拼接,将“ab”放入StringTable中。
第4行 String s4=s1+s2; s1,s2已经存在于StringTable中,执行第4步其实就是执行new StringBuilder().append(“a”).append(“b”).toString();再把这个结果存于堆中,因为是new出来的,注意不是在StringTable中,这也是与第三行不同的地方。 所以s4!=s5。有的小伙伴会问这与第3行有什么区别。这其实是javac在编译期的优化,第3行“a”和“b”结果已经在编译期间确定,而s1,s2是变量,会发生改变,需要在运行期间用StringBuilder()拼接。
第5行与第3行一样, 将“ab”放入StringTable中,但“ab”已经存在。所以s3s5;s3!=s4.
第6行p2.intern(), 将这个字符串对象尝试放入串池中,如果有则并不会放入。如果没有就不会放入,并把串池中的对象返回。(jdk1.7 1.8, jdk 1.6是复制一份对象放入串池中)。
p2是堆中的“cd”对象尝试放入串池中,此时串池中还没有“cd”;把字符串对象放入池中,并返回这个对象给p3.所以p1 p2是同一个对象p1p2,p3p1。若是1.6则p2!=p1,因为是拷贝的。