如果您有两个字符串的实例,并且它们是平等的,则在Java中,它们将共享相同的内存。这是如何在引擎盖下实施的?

编辑:我的应用程序使用大量的字符串对象,其中许多对象是相同的。使用Java String Constant池的最佳方法是什么,以免创建自定义的轻量级实现?

有帮助吗?

解决方案

查看的源代码 java.lang.String (整个Java API的来源是JDK的一部分)。

总结:一个字符串包裹一个子序列 char[]. 。那个支持 char[] 永远不会修改。这是通过既没有泄漏也不捕获的来实现的 char[] 外面 String 班级。但是,有几个 Strings 可以共享相同的 char[] (请参阅实施 String.substring).

如其他答案中所述,还有一种实习的机制。

其他提示

如果您有两个字符串的实例,并且它们是平等的,则在Java中,它们将共享相同的内存

这实际上不是100%正确的。

这篇博客文章是一个不错的解释 为什么这是这样,以及什么 字符串常数池 是。

字符串文字在Java中实施,因此实际上只有一个带有多个引用的字符串对象(当它们相等时,并非总是如此)。请参阅Java.net文章 关于实习生() 更多细节。

部分中还有一个很好的例子/解释 3.10.5字符串文字 在谈论何时实习以及何时与众不同的JL中。

这不是真的。例子:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true

但:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false

现在,第二种形式不建议。有些人(包括我)认为 String 甚至不应该有公共构造师。以上更好的版本是:

String s1 = new String("hello").intern();
String s2 = new String("hello").intern();
System.out.println(s1 == s2); // true

显然,您不需要做到这一点 String. 。这是说明性的。

重要的一点是,如果您通过了 String 或从您不能依靠的功能中获得一个 String 存在 典范. 。一种 典范 Object 满足这种平等:

a.equals(b) == b.equals(a) == (a == b)

对于非 -null 实例 a, b, 给定的 Class.

为了回答您编辑的问题,Sun JVM有一个 -XX:+StringCache 选项,在我的观察中,可以大大减少弦重量应用程序的内存足迹。

否则,您可以选择实习弦,但是我会谨慎。非常大,不再引用的字符串仍将在JVM的生活中使用记忆。

编辑(响应评论):我首先从 这里:

-XX:+StringCache启用通常分配的字符串的缓存。

汤姆·霍顿 描述某种类型的缓存以改善一些基准。当我提出的想法时,我的观察是,记忆足迹(完整的垃圾收集之后)因没有它而下降了。它不是记录的参数,实际上可能只是针对某些基准进行优化。我的观察是它有所帮助,但我不会基于它建立重要的系统。

要小心的两件事:

  1. 不使用 new String("abc") 构造函数,只需使用文字 "abc".
  2. 学习使用 实习生() 字符串类中的方法。特别是当将字符串连接在一起或将char数组/字节数组/等转换为字符串时。

intern() 返回总是汇总的字符串。

如果您的相同的字符串来自一组固定的可能值,那么您想要的是类型安全的枚举。它不仅会减少您的字符串计数,而且还可以实现更扎实的应用程序。您的整个应用程序将知道此字符串附有语义,甚至可能采用一些便利方法。

我最喜欢的优化始终是可以作为制作代码的优化 更好的, ,不只是更快。在10中,有9次用混凝土类型替换字符串会导致更正确和自我纪录的代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top