您将编译时间复杂性与运行时复杂性混淆了。
加载类时,是的,它会搜索每个文字是否已经存在(尽管我想它会使用哈希图进行 O(1) 查找而不是您的建议)。
当代码运行时,它引用了内存中的字符串,因此没有比非文字额外的成本。
所以是的,文字是被实习的。根据 String 的 Javadoc,
一个字符串池,最初是空的,由 String 类私下维护。
您可以调用intern()
String 以将其添加到此池中。从逻辑上讲,如果a.equals(b)
then a.intern() == b.intern()
, since.intern()
保证从唯一池返回。
例子:
class InternTest {
// assuming InternTest is the only class, internPool.size = 0
String x = "ABC"; // interned at class load, internPool.size = 1
String y = "DEF"; // interned at class load, internPool.size = 2
String z = "ABC"; // interned at class load, but match found - size = 2 still
void foo() {
// random int is just a mechanism to get something that I know won't
// be interned at loadtime - could have loaded from file or database too
int i = (new java.util.Random()).nextInt(1000) + 100;
int j = i;
String s = String.valueOf(i); // not yet interned, size = 2 still
String t = String.valueOf(j); // not yet interned, size = 2 still
String sIntern = s.intern(); // manually interned, size = 3 now
String tIntern = t.intern(); // manually interned, match found, size = 3 still
System.out.println("equals: " + (s.equals(t))); // should be true
System.out.println("== raw: " + (s == t)); // should be false, different variables
System.out.println("== int: " + (sIntern == tIntern)); // should be true, from unique pool
System.out.println("x and z: " + (x == z)); // should be true, interned at class load
}
public static void main(String[] args) {
(new InternTest()).foo();
}
}
运行时的结果:
C:\Documents and Settings\glowcoder\My Documents>java InternTest
equals: true
== raw: false
== int: true
x and z: true
我应该指出,这个假设永远不会成立。Java 语言本身有许多String
s 将在我们String
有机会看到曙光之前被实习。然而,假设一切都是按顺序加载的,如果你只考虑被实习的字符串的增量,并且假设没有与现有实习生发生冲突(我们都知道实习生可能很挑剔,充满戏剧性,对吧?窃笑)那么数字确实表明字符串池大小的增量。