在周志明的《深入理解java虚拟机》,2nd,p57中有一部分代码
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
对照着intern()看了api源码上的javadoc注释
/**
* Returns a canonical representation for the string object.
*
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
*
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
*
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
*
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* The Java™ Language Specification.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*/
public native String intern();
个人理解是:
如果调用intern之前字符串已存在,返回字符串对象,否则返回字符串引用。“首次出现”返回引用。
讲到在jdk 7之前的版本中,intern() 会把首次遇到的String实例复制到永久代中,返回的是永久代中String实例的引用。由StringBuilder创建的String实例在堆上,所以不是同一个引用,返回false。
按照jdk历史版本的内存区域分布图,得知jdk 7之前的执行结果为
false
false
jdk 7及以后的执行结果为
true
false
但是不太理解书籍里讲到的
“java”这个字符串在执行StringBuilder的toString()之前已经出现过,字符串常量池已经有它的引用了,不符合“首次出现”的原则。
感觉这里作者埋坑了,在看到3rd版里讲到这个地方,说读者有这个疑问,给了注释讲到说是在sun.misc.Version中已经存在,提到了知乎里的作者RednaxelaFX在https://www.zhihu.com/question/51102308/answer/124441115
里做了讲解, 讲的很好。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)