JDK1.8 String类 intern方法详解
官方文档
public String intern()
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is 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.
- Returns:
- a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
翻译:当调用字符串str 的intern方法时,如果常量池中已经包含了一个字符串equalsstr,则直接从池中返回这个字符串的引用,否则,把字符串str添加到池中并且返回其引用。
当且仅当s.equals(t)返回true时, t, s.intern() == t.intern()才返回true。(注意jdk7及以上常量池中才开始存的地址引用,之前的都是直接把对象copy一份存到常量池,这点《深入理解java虚拟机》中有特别说明)
《深入理解Java虚拟机》一书中,周志明老师举例用的时用的如下例子:
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern()==str1);//输出true
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);//输出false
}
}
以上程序输出:true false
原因解释:
用new命令时,虚拟机都会在堆中开辟一块新的内存,当程序执行完new StringBuilder("计算机").append("软件").toString()后,产生拼接后的“计算机软件”字符串在常量池是不存在的,所以把其堆地址存入常量池中,此时str1.intern()返回的是堆中刚创建的“计算机软件“的地址,
str1.intern()==str1返回true。
第二个字符串”java”,这个是一个特殊字符串,无论我们是否创建它,虚拟机的常量池中都包含的有该字符串。由于常量池已经包含”java“,所以str2.intern()返回的是常量池本身就存在的"java"字符串地址的引用。而str2是我们new出来的,它指向的时我们在堆中新开辟的一个地址,故
str2.intern() == str2返回false。
还有个问题时起初不理解为啥非要用StringBuilder类后面加append的方式做实验,把append后面去掉后发现输出的结果又变了,第一个输出也变成false了。
String str1 = new StringBuilder("计算机").toString();
System.out.println(str1.intern()==str1);//输出false
两次输出为啥不一样呢?就是去掉了append,因为当我们new StringBuilder("计算机")时,已经包含了“计算机”字符串,它会放入常量池中去,其地址不是我们主动new StringBuilder的这个地址,所以返回false。
关于这点网上有个流行的面试题目:String s = new String("xxx")创建了几个对象? 答案是两个。一个时"xxx",另一个时new 出来的,前面说道只要时new 都会重新在堆内存分配地址。

浙公网安备 33010602011771号