我看到很多类似这样的遗留代码:
class A {
public static final String CONSTANT = "value".intern();
...
}
我不认为需要使用intern()函数,因为在Javadoc中可以读到:"所有字面值字符串和字符串类型的常量表达式都会被池化(interned)"。这是有意义的吗?也许在语言的早期版本中有些意义?
我看到很多类似这样的遗留代码:
class A {
public static final String CONSTANT = "value".intern();
...
}
我不认为需要使用intern()函数,因为在Javadoc中可以读到:"所有字面值字符串和字符串类型的常量表达式都会被池化(interned)"。这是有意义的吗?也许在语言的早期版本中有些意义?
这是一种技术,用于确保CONSTANT
实际上不是常量。
当Java编译器看到对final static primitive或String的引用时,它将该常量的实际值插入使用它的类中。如果您然后更改定义类中的常量值但不重新编译使用类,则它将继续使用旧值。
通过在“常量”字符串上调用intern(),编译器不再认为它是静态常量,因此使用类将在每次使用时实际访问定义类的成员。
JLS 引用:
intern()
函数在使用常量字符串时是浪费时间的,因为根据 The Java® Language Specification 第 3.10.5 节 String Literals,字面值已经被池化了。
以下摘自Java SE 8版本:
此外,字符串文字始终引用 String 类的相同实例。 这是因为字符串字面量(更一般地说,是常量表达式的值 §15.28)会被 "interned",以共享唯一实例,使用 String.intern 方法。
我猜编码者没有意识到这个事实。
编辑:
如kdgregory所指出的,这个常量可能会对内联有影响。
1- https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5
我使用intern()进行“锁定”。例如,假设我有一个“交易记录”“存储库”。当我编辑和更新一项交易时,我希望锁定该交易;我可能会选择锁定tradeId.intern(),这样我就不必担心交易克隆四处漂浮。我不确定每个人是否都喜欢这种用法。
这假设id字段不太可能意外与另一个域对象的id字段发生冲突——例如,tradeId不会碰巧与account_number发生冲突,在这种情况下,也可以执行操作。
synchronized(account.getAccountNumber().intern()) {...}
查看示例