题目1
String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";
String s4 = s1 + s2;
System.out.println(s3==s4);
上面的结果返回是false,分析如下,首先s1和s2被常量a和常量b赋值,那么a和b会放入StringTable串池中,而对于s3由于是两个常量拼接,javac会在编译期间直接将这两个常量拼接为常量ab,并放入串池中,s4是两个变量拼接,底层实际是调用了new StringBuilder().append(“a”).append(“b”).toString(),而toString()底层是new String(),因此s4在堆中,是堆中的对象,而s3在串池中,是串池的对象,自然结果返回false。
题目2
String s1 = new String("a") + new String("b");
String s2 = s1.intern();
System.out.println(s2=="ab");
上面的结果返回是true,分析如下,首先第一行会将常量a和常量b放入串池中,并会在堆中创建值为a、值为b以及值为ab的字符串对象(分析过程与前一个相同不再赘述),对于jdk1.7及以上版本,s1.intern()是将s1即堆中的对象放入串池并返回串池中的对象,也就是s1,当判断s2==“ab"时,常量"ab"直接从串池中取,而s2也是串池中的"ab”,因此返回true。
intern方法在jdk1.7及以后是将字符串对象放入串池中,如果串池中有则不会放入,如果串池中没有则会放入,不管有没有最终都是返回串池中的对象,而以前的版本是将字符串对象放入串池中,如果串池中有则不会放入,如果串池中没有则会将该字符串复制一份把复制的放入,不管有没有最终也都是返回串池中的对象
题目3
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);//false
System.out.println(s3==s5);//true
System.out.println(s3==s6);//true
String x2 = new String("c") + new String("d");
x2.intern();
String x1 = "cd";
System.out.println(x1==x2);
分析如下,第一、二行会将常量a和b放入串池,第三行由于是两个常量拼接,javac会在编译期间直接将这两个常量拼接为常量ab,并放入串池中,第四行会在堆中新建ab对象,第五行得到的就是串池中的对象,第六行得到的是串池中的对象。
第十行会将常量c和常量d放入串池,并在堆中新建cd对象,第十一行,对于jdk1.7及以后会将堆中的cd对象放入串池,第十二行会从串池中取cd,因此返回true,但对于以前的版本第十一行会将cd对象复制一份,将对象的副本放入串池,第十二行得到的是cd对象的副本,因此返回false。