我想问一个关于在 Java 中避免字符串重复的问题。
context 是:带有标签和属性的 XML,如下所示:
<product id="PROD" name="My Product"...></product>
使用 JibX,此 XML 在类中编码/解码如下:
public class Product{
private String id;
private String name;
// constructor, getters, setters, methods and so on
}
程序是一个长时间的批处理,所以Product对象被创建、使用、复制等。
嗯,问题是: 当我使用 Eclipse 内存分析器 (MAT) 等软件分析执行时,我发现了几个重复的字符串。例如,在 id 属性中,PROD 值在 2000 个实例左右重复等。
如何避免这种情况? Product 类中的其他属性可能会在执行过程中改变它们的值,但是像 id、name... 这样的属性不会经常改变。
我已经阅读了一些关于 String.intern() 方法的内容,但我还没有使用过,我不确定它是否是解决此问题的方法。我可以在这些属性中定义最频繁的值,例如类中的 static final 常量吗?
我希望我已经以正确的方式表达了我的问题。 非常感谢任何帮助或建议。提前致谢。
最佳答案
如果您确实遇到问题,
实习 将是正确的解决方案。 Java 将字符串文字和许多其他字符串存储在一个内部池中,每当即将创建一个新字符串时,JVM 首先检查该字符串是否已在池中。如果是,它不会创建新实例,而是将引用传递给 interned String 对象。
有两种方法可以控制这种行为:
String interned = String.intern(aString); // returns a reference to an interned String
String notInterned = new String(aString); // creates a new String instance (guaranteed)
因此,也许,库确实为所有 xml 属性值创建了新实例。这是可能的,您将无法更改它。
intern 具有全局影响力。一个 interned String 可以立即“用于任何对象”(这个观点并没有真正意义,但它可能有助于理解它)。
所以,假设我们在类 Foo
中有一行,方法 foolish
:
String s = "ABCD";
字符串文字会立即被保留。 JVM 检查“ABCD”是否已经在池中,如果不存在,则将“ABCD”存储在池中。 JVM 将对驻留字符串的引用分配给 s
。
现在,也许在另一个类 Bar
中,在方法 barbar
中:
String t = "AB"+"CD";
然后 JVM 会像上面一样实习“AB”和“CD”,创建连接的字符串,看,如果它已经被插入,嘿,是的,并将对实习字符串“ABCD”的引用分配给 t
。
调用 "PROD".intern()
可能成功也可能失败。是的,它将实习字符串 "PROD"
。但是有可能,jibx 确实为属性值创建了新的字符串
String value = new String(getAttributeValue(attribute));
在这种情况下,value 将没有对内部字符串的引用(即使 "PROD"
在池中),而是对新字符串实例的引用在堆上。
而且,对于您命令中的另一个问题:这仅在运行时发生。编译只是创建类文件,字符串池是对象堆上的数据结构,由执行应用程序的 JVM 使用。
关于java - 避免 Java 中的重复字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5076099/