我对 Java 的 String.intern() 方法文档感到困惑。官方文档指出:
返回字符串对象的规范表示。一池 字符串最初为空,由 String 类私有维护。 当调用intern方法时,如果池中已经包含一个 由 equals(Object) 确定的字符串等于此 String 对象 方法,然后从池中返回字符串。否则,这 String对象被添加到池中并引用此String 对象已返回。
但是当我们使用new创建一个String时,字符串字面量不是已经添加到了String Pool中了吗?例如:
String s1 = new String("Java"); // Creates 2 objects
那么 intern() 到底什么时候才真正向池中添加新字符串呢?该文档似乎有误导性,或者我遗漏了什么?
java.lang.String
类有多个构造函数,它们不涉及字符串文字。这意味着调用
String s = new String(new byte[] {0x68, 0x69});
不会将创建的字符串放入字符串池中,但
s.intern()
会(如果字符串池中还没有这样的字符串)。请参阅以下示例:
public static void main(String[] args) {
String f1 = new String(new byte[] {0x68, 0x69});
System.out.println(f1);
String f2 = new String(new byte[] {0x68, 0x69});
System.out.println(f2);
System.out.println("Equals: "+f1.equals(f2));
String i1 = f1.intern();
System.out.println("ref check for 1: "+(i1 == f1));
String i2 = f2.intern();
System.out.println("ref check for 2: "+(i2 == f2));
System.out.println("ref check both: "+(i1 == i2));
}
这将生成以下输出:
hi
hi
Equals: true
ref check for 1: true
ref check for 2: false
ref check both: true
如您所见,字符串彼此相等。第一个
intern()
调用会将字符串放入字符串池中,第二个 intern()
调用则不会。但由于原始 f1
字符串已首先添加到字符串池中,因此所有其他 intern()
调用将返回相同的实例(对于同一字符串)。
另外,当我实际测试您的代码时,我没有得到与文字 String 相同的对象
s1 = new String("Java");
不会返回与文字“Java”相同的对象。如果我随后调用 s1.intern()
,我确实会得到与原始文字相同的对象。
public static void main( String[] args ) {
System.out.println( Objects.toIdentityString( "Java" ) );
String s = new String( "Java" );
System.out.println( Objects.toIdentityString( s ) );
s = s.intern();
System.out.println( Objects.toIdentityString( s ) );
}
Output:
run:
java.lang.String@63c12fb0
java.lang.String@b1a58a3
java.lang.String@63c12fb0
BUILD SUCCESSFUL (total time: 0 seconds)