38

我看到很多这样的遗留代码:

class A {
    public static final String CONSTANT = "value".intern();
    ...
}

我看不出使用 intern() 的任何原因,正如在 Javadoc 中可以读到的那样:“所有文字字符串和字符串值常量表达式都是实习的。” 是否有这样的意图,也许在过去的语言版本中?

4

4 回答 4

69

这是一种确保它CONSTANT实际上不是常数的技术。

当 Java 编译器看到对最终静态原语或字符串的引用时,它会将那个常量的实际值插入到使用它的类中。如果您随后更改定义类中的常量值但不重新编译使用类,它将继续使用旧值。

通过在“常量”字符串上调用 intern(),编译器不再将其视为静态常量,因此使用类实际上将在每次使用时访问定义类的成员。


JLS 引用:

于 2009-12-02T15:43:06.240 回答
17

使用intern()常量字符串文字是浪费时间,因为文字已经按照第3.10.5 节的规定进行了实习。Java® 语言规范的字符串文字

引用 Java SE 8 版本:

此外,字符串字面量总是引用 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串(第 15.28 节) - 是“内部的”,以便使用 String.intern 方法共享唯一实例。

我猜编码器不理解这个事实。

编辑:

正如kdgregory指出的那样,这个常量的内联方式会产生影响。

1 - https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5

于 2009-12-02T15:31:39.143 回答
8

不久前,我对所有来自类文件的字符串(用于类文件解析器)进行了实习()。Intern()ing 使程序使用更少的内存(在这种情况下不会像其他人指出的那样),但它确实显着减慢了程序的速度(我认为解析所有 rt.jar 需要 4 秒,而这个改变让它超过 8 秒)。当时研究它(我认为是 JDK 1.4),intern() 代码非常丑陋且速度较慢,可能需要这样做。

如果我要考虑在我的代码中调用 intern(),我会首先在没有 intern() 的情况下对其进行分析,然后使用 intern() 分析它的内存和速度,看看哪个对更改“更糟”。

于 2009-12-02T15:43:18.983 回答
0

我使用了 intern() 来“锁定”。例如,假设我有一个“交易记录”的“存储库”。当我编辑和更新交易时,我想锁定交易;相反,我可能会锁定 tradeId.intern(),这样我就不必担心交易的克隆会四处飘荡。我不确定是否每个人都喜欢这种用法。

这假设 id 字段不太可能意外与另一个域对象的 id 字段发生冲突 - 例如,tradeId 不会碰巧与 account_number 发生冲突,其中一个人也可能正在这样做

synchronized(account.getAccountNumber().intern()) {...}

例子

于 2012-01-10T19:39:41.167 回答