一、问题由来
前几天去实习面试,遇到了这么一个笔试题
String s1 = new String("1"); s1.intern(); String s2 = "1"; System.out.println(s1 == s2); //false String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); //true
二、问题解决
1、分析
两者最大的差别就是一个是直接new的对象,而一个是通过字符串拼接所得到的。如果拼接符号左右有至少一个是String类型的变量,就会创建一个StringBuilder对象,创建完成后调用toString方法生成的对象,相当于new String("11"),关键就在于这个对象是不会在StringTable创建的。
2、解决
这里的两次比较其实都是在比较引用地址,而第一次为false的主要原因是因为 一个是StringTable中的“1” 而另一个是在堆中创建的new String("1"),他们的引用地址本来就不一样,所有是false。但是第二次比较时,在字符串拼接时StringBuilder对象调构造方法后会在堆空间生成“11”的String对象而不会在常量池中,所有是true;可以理解为StringTable中存在两个“1”对象,但拼接过后堆中会出现一个“11”,故而引用是相同的。
3、intern()方法
查询字符串常量池中是否具有该字符串,如果有,返回该字符串的索引,如果没有,在字符串常量池中创建该字符串然后返回索引。