看到一个简单的代码:
public static void main(String[] args) throws InterruptedException {
String s0 = new StringBuilder().append("he").append("llo").toString();
System.out.println(s0.intern() == s0);
String s1 = new StringBuilder().append("ja").append("va").toString();
System.out.println(s1.intern() == s1);
}
运行结果如下:
true
false
在1.6中,常量池在方法区,intern()会把首次遇到的字符串实例复制到永久代中,返回的也是这个永久代中字符串实例的引用;
而在1.7,1.8中,String 的 intern 方法首先将尝试在常量池中查找该对象的引用,如果找到则直接返回该对象在常量池中的引用地址;若不存在就会将当前字符串放入常量池中;
看看上面代码的例子:
s0在堆中创建了“hello”这个字符串对象,然后这个“hello”被加到常量池中,s0返回的其实是常量池中的引用地址,s0.intern()也取的是常量池的引用地址,所以s0.intern() == s0.
s1的情况特殊,这是因为常量池在初始化的时候会内置一些字符串常量进去,在rt.jar里面已经用到了“java”这个字符串,那么s1指向的是在堆中新建的的“java”字符串,s1.intern()指向的是常量池中的“java”,虽然常量池也位于堆中,但是这是两个不同的位置,所以s1.intern() != s1.
参考:
https://tech.meituan.com/in_depth_understanding_string_intern.html
网友评论