String的intern方法(仅代表个人理解)
首先要明白:
1、直接使用双引号声明出来的的String对象是存储在常量池中,new出来的对象存在于堆中
2、如果不是双引号声明的String对象,可以使用String的intern方法。intern方法会从字符串常量池中查询当前字符串是否存在,若不存在则会将当前字符串放入常量池中
public static void main(String[] args) {
String s = new String(“1”);
s.intern();
String s2 = “1”;
System.out.println(s == s2);
String s3 = new String(“1”) + new String(“1”);
s3.intern();
String s4 = “11”;
System.out.println(s3 == s4);
}
上面的代码打印结果是在jdk7之后是 false true,这是为什么呢?
首先说intern的用法,上面说到intern会判断常量池中是否存在当前字符串,若不存在则将当前字符串放入常量池中,那么我们就可以来解析第二个的答案,首先 String s3 = new String(“1”) + new String(“1”);这行代码生成了四个对象,一个常量池中的“1”,和一个s3指向的对象,和两个匿名的new String(“1”),当然,我们不关心后面两个,这行代码执行完了之后常量池中是没有“11”的,当s3.intern();执行时,jdk6的做法是将“11”往常量池中存放一份,但是jdk7将常量池放入堆中,此时常量池可存储字符串也可存储字符串的引用。所以当s3.intern执行时常量池中存入了一份“11”的引用,也就是s3,此时再创建s4则会直接用“11”的引用所以结果自然就是true了。
那再说回上面String s = new String(“1”);是创建了两个对象,一个是常量池中的“1”,一个是s对象,此时调用intern方法,常量池中已经有一个“1”,所以不会再次生成,接下来String s2 = “1”;会直接引用常量池中的“1”,和s对象的地址自然不一样了,所以结果也就是false了。
还需要注意的是,在对比了字节码的时候发现,创建s3的时候其实是使用了StringBuilder方法进行的拼接,拼接完成之后调用toString方法,最后调用intern方法;
以上观点均为个人观点,如有错误,欢迎留言指正,感谢谅解!