java如何在引擎盖下实现字符串的flyweight模式?

Dan*_*Dan 17 java design-patterns flyweight-pattern

如果你有两个String实例,并且它们是相同的,那么在Java中它们将共享相同的内存.这是如何在引擎盖下实施的?

编辑:我的应用程序使用大量的String对象,其中许多是相同的.使用Java String常量池的最佳方法是什么,以避免创建自定义flyweight实现?

mat*_*t b 12

如果你有两个String实例,并且它们是相同的,那么在Java中它们将共享相同的内存

这实际上不是100%真实.

这篇博客文章很好地解释了为什么会这样,以及String常量池是什么.


mer*_*ike 7

查看源代码java.lang.String(整个java api 的源代码是JDK的一部分).

总结一下:一个String包含了一个子序列char[].这种支持char[]永远不会被修改.这是通过既没有泄漏也没有char[]String课堂外捕获它来实现的.但是,有几个Strings可以共享相同的内容char[](请参阅实现String.substring).

如其他答案所述,还有实习机制.


Bil*_*ard 6

字符串文字是用Java实现的,所以实际上只有一个String对象有多个引用(当它们相等时,情况并非总是如此).有关更多详细信息,请参阅java.net文章有关intern()的所有信息.

3.10.5 JLS的字符串文字中还有一个很好的例子/解释,它讨论了字符串何时被实现以及它们何时是不同的.


cle*_*tus 5

这不是必须的。例子:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
Run Code Online (Sandbox Code Playgroud)

但:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false
Run Code Online (Sandbox Code Playgroud)

现在不鼓励第二种形式。有些人(包括我)认为这String甚至不应该有一个公共构造函数。上面的更好版本是:

String s1 = new String("hello").intern();
String s2 = new String("hello").intern();
System.out.println(s1 == s2); // true
Run Code Online (Sandbox Code Playgroud)

显然,您不需要为常量执行此操作String。这是说明性的。

关于这个最重要的一点是,如果你传入一个String或一个函数得到一个你不能依赖String规范。一个规范 Object满足这个等式:

a.equals(b) == b.equals(a) == (a == b)
Run Code Online (Sandbox Code Playgroud)

用于非null实例ab,给定的Class

  • 关于实习的一个警告是它使用 PermGen 内存,这可能导致非常讨厌的 `OutOfMemoryError`。如果需要字符串池,自定义池通常是更好的选择:http://hype-free.blogspot.com/2010/03/stringintern-there-are-better-ways.html (2认同)