字符串管理方式的实际实现在 Java 中不应该是重要的,除了以下保证:
- 字符串 x = "你好"; 字符串 y = "你好"; // 保证 x == y
- 字符串 x = "你好"; 字符串 y = new String("hi"); // 不保证 == 尽管有可能 !=
- 字符串 x = new String("hi"); 字符串 y = new String("hi"); // 保证 != 但 x.equals(y)
- 字符串 x = "你好"; String y = new String("hi").intern(); // 保证 x == y
这些是字符串的规则......
过去(这将随着 Java8 改变),String.intern()
字符串常量 ( String x = "hi"
) 是在内存模型中的 PermGen 空间上分配的。
结果,它们具有不同的 GC 机制,String.intern()
即使您有大量可用堆空间(PermGen 通常小于 128MB),也可能会耗尽内存。
分配的字符串new String(....)
在常规堆上,并具有标准的 GC 机制。
至于为什么你/我们使用 来创建新的字符串实例new String ("...")
,我只能想到一个地方,只有这样做才有意义,那就是如果有人想使用生成的对象作为同步锁。这在调试东西时是有意义的......但没有多大意义。您必须使用“新”,以免无意中使用与其他同步代码相同的 String 对象。
在一般的 Java 编码实践中,我通常没有看到人们使用new String ("....")
. 现实情况是,在大多数情况下,人们只是简单地使用字符串连接运算符等。但是,这并不意味着这样做是错误的new String(...)
当我查看 String 的源代码时,我发现代码在很大程度上依赖于 String 的不可变性。因此,例如, new String(new String("hi")); 只创建一个 char 数组,并且在两个 String 实例中共享。(无论如何内部实例都会被GC)。