您将编译时间复杂性与运行时复杂性混为一谈。
当这个类被加载时,是的,它做了一个搜索,看看每个文字是否已经存在(尽管我认为它会使用散列表进行O(1)查找而不是提议)。
代码运行时,它具有对内存中字符串的引用,因此没有额外的开销而非非文字。
所以是的,文字是interned。根据字符串Javadoc,
字符串池,最初是空的,由类String私人维护。
您可以在字符串上调用intern()
将其添加到此池中。从逻辑上看,如果a.equals(b)
然后a.intern() == b.intern()
,因为.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
有机会看到白天之光之前会被实施。然而,假设一切都按顺序加载,如果你只考虑字符串的增量,并且假设没有与现有实习生发生冲突(我们都知道实习生可能很挑剔并且充满戏剧性,对吧?snicker),那么这些数字确实指示字符串池的大小的增量。
我将您对“JSK 1.3”的引用修改为官方的JavaDoc。 –
@joachim Sauer谢谢,但最后一句来自你删除的(http://www.janeg.ca/scjp/lang/strLiteral.html)。你能反映一下吗?或者我会的。 – RENO
我删除了它,因为上面链接的JavaDoc是引用的授权原始源,并且该页的质量有问题(没有“JSK 1.3”这样的东西,并且它实际上并没有链接到它的任何源) 。 –