何时在string文字上使用intern()

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

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

我没有看到intern()的任何理由,因为在Javadoc中可以这样理解:“所有文字string和string值的常量expression式都被禁止了。 有没有这个意图,也许在过去的语言修订?

这是确保CONSTANT实际上不是一个常量的技术。

当Java编译器看到对最终静态基元或string的引用时,它会将该常量的实际值插入到使用它的类中。 如果您然后更改定义的类中的常量值,但不重新编译使用的类,它将继续使用旧的值。

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


JLS引用:

  • 定义一个编译时常量: http : //docs.oracle.com/javase/specs/jls/se6/html/expressions.html#5313

  • 对编译时常量的更改(大约在页面的一半)的含义: http : //docs.oracle.com/javase/specs/jls/se6/html/binaryComp.html#45139

intern()和常量string的使用是浪费时间,因为字面量已经按照3.10.5节的规定被实现了。 Java®语言规范的 string文字

从Java SE 8版引用:

而且,一个string文字总是引用类String的同一个实例。 这是因为string文字 – 或者更一般地说,是常量expression式(§15.28)的值的string – 被“interned”,以便使用方法String.intern共享唯一的实例。

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

编辑:

正如kdgregory所指出的那样,这个常数可能会被内联。

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

前段时间我intern()编辑所有来自类文件的string(用于类文件parsing器)。 Intern()ing使程序使用较less的内存(在这种情况下不会像其他人指出的那样),但它确实减慢了程序的速度(我认为需要花费4秒来parsing所有的rt.jar,超过8秒)。 在当时的考虑(是JDK 1.4我认为)intern()代码是相当丑陋和慢,可能需要。

如果我考虑在代码中调用intern(),我会首先在没有intern()的情况下对其进行configuration,然后使用intern()对内存和速度进行configuration,并查看哪一个更糟糕。

我用intern()来“locking”。 例如,假设我有一个“贸易logging”的“存储库”。 当我编辑和更新交易时,我想locking交易; 我可能会locking在tradeId.intern(),这样我就不用担心浮动交易的克隆了。 我不确定每个人都喜欢这个用法。

这假设id字段不可能意外地与另一个域对象的id字段相冲突 – tradeId不会碰巧与account_number冲突,例如,也可能在做

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

看例子