题目
public class Test { public static void main(String[] argss) { String str1 = new StringBuilder("58").append("tongcheng").toString(); System.out.println(str1); System.out.println(str1.intern()); System.out.println((str1 == str1.intern())); System.out.println(); String str2 = new StringBuilder("ja").append("va").toString(); System.out.println(str2); System.out.println(str2.intern()); System.out.println((str2 == str2.intern())); } }
运行结果
58tongcheng 58tongcheng true java java false
原因
- String str1在方法里创建了一个变量,new StringBuilder(“58”)在堆内存中创建了对象,调用对象的append方法,把这个StringBuilder里的字符串加成了"58tongcheng",然后调用toString创建并返回了一个String对象,这个返回的String对象仍然在堆内存里,str1指向了这个String对象。
- 打印str1
- 调用字符串的intern方法,前往常量池中查询是否存在这个字符串,发现没有存在,则将该字符串对象加入了常量池中,并返回了该字符串对象。(String对象,内容为:“58tongcheng”)
- 判断str1和str1.intern()是否相等,也就是判断str1指向的对象和常量池中"58tongcheng"这个字符串对应的对象的地址是否相同,由于前面调用的时候把这个字符串对象加入进了常量池,因此这次返回的其实还是str1之前指向的那个String对象,判断这两个String对象地址是否相等返回true
- 打印空行
- String str2在方法里创建了一个变量,new StringBuilder(“ja”)在堆内存中创建了对象,调用对象的append方法,把这个StringBuilder里的字符串加成了"java",然后调用toString创建并返回了一个String对象,这个返回的String对象仍然在堆内存里,str1指向了这个String对象。
- 打印str1
- 调用字符串的intern方法,前往常量池中查询是否存在这个字符串,发现存在,存在的原因是,java默认加载了java.lang包下的所有类,而String类就在这个包下,因此加载类的时候这个java字符串是一个包名,已经被加载进了String类的静态常量池了,那么这次打印的是常量池中的"java"字符串对应的String对象。(String对象,内容为:“java”)
- 判断str1和str1.intern()是否相等,也就是判断str1指向的对象和常量池中"java"这个字符串对应的对象的地址是否相同,由于前面调用的时候这个字符串对象是新创建的存在于堆内存中的,调用intern方法返回的String对象是之前在加载java.lang下的String类时就已经被加载进了String类的常量池了的,因此两个String对象内存地址不相等返回false。