您将编译时间复杂性与运行时复杂性混淆了。
当加载类时,是的,它会进行搜索以查看每个文字是否已经存在(尽管我想它会使用哈希图进行 O(1) 查找而不是您的建议)。
当代码运行时,它会引用内存中的字符串,因此与非文字相比没有额外的成本。
所以是的,文字被拘留了。根据 String 的 Javadoc,
字符串池最初是空的,由 String 类私有维护。
您可以调用intern()
在字符串上将其添加到该池中。从逻辑上看,如果a.equals(b)
then a.intern() == b.intern()
, since .intern()
保证从唯一的池中返回。
Example:
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
在我们之前会被实习的String
我们有机会重见天日。然而,假设所有内容都是按顺序加载的,如果您只考虑被实习生的字符串增量,并假设与现有实习生没有冲突(我们都知道实习生可能很挑剔并且充满戏剧性,对吧?snicker)那么这些数字确实表示字符串池大小的增量。