何时对字符串文字使用 intern()
我看到很多这样的遗留代码:
class A {
public static final String CONSTANT = "value".intern();
...
}
我没有看到 intern() 的任何原因,正如在 Javadoc 中可以读到的那样:“所有文字字符串和字符串值常量表达式都被实习。”也许在该语言过去的修订中是否有某种意图?
I see a lot of legacy code like this:
class A {
public static final String CONSTANT = "value".intern();
...
}
I don't see any reason for the intern(), as in the Javadoc one can read: "All literal strings and string-valued constant expressions are interned." Is there some intent of this, maybe in past revisions of the language?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一种确保
CONSTANT
实际上不是常量的技术。当 Java 编译器看到对最终静态基元或字符串的引用时,它会将该常量的实际值插入到使用它的类中。如果您随后更改定义类中的常量值但不重新编译使用类,它将继续使用旧值。
通过对“常量”字符串调用 intern(),编译器不再将其视为静态常量,因此使用类实际上将在每次使用时访问定义类的成员。
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
This is a technique to ensure that
CONSTANT
is not actually a constant.When the Java compiler sees a reference to a final static primitive or String, it inserts the actual value of that constant into the class that uses it. If you then change the constant value in the defining class but don't recompile the using class, it will continue to use the old value.
By calling intern() on the "constant" string, it is no longer considered a static constant by the compiler, so the using class will actually access the defining class' member on each use.
JLS citations:
definition of a compile-time constant: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#5313
implication of changes to a compile-time constant (about halfway down the page): http://docs.oracle.com/javase/specs/jls/se6/html/binaryComp.html#45139
将
intern()
与常量字符串文字一起使用是浪费时间,因为文字已经按照 3.10.5。 Java® 语言规范<的字符串文字 /em>。引用 Java SE 8 版本:
我猜编码员没有意识到这一事实。
编辑:
正如kdgregory指出的那样,这个常量的内联方式会受到影响。
1- https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10。 5
The use of
intern()
with the constant string literal is a waste of time as the literal will already be interned as specified by section 3.10.5. String Literals of The Java® Language Specification.Quoting from Java SE 8 Edition:
I guess the coder didn't appreciate this fact.
Edit:
As kdgregory has pointed out there is an impact on how this constant may be inlined.
1- https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5
不久前,我实习了来自类文件的所有字符串(对于类文件解析器)。 Intern()ing 使程序使用更少的内存(在这种情况下不会像其他人指出的那样),但它确实显着减慢了程序的速度(我认为解析所有 rt.jar 需要 4 秒,并且该更改将它超过 8 秒)。当时(我认为是 JDK 1.4)来看,intern() 代码非常丑陋,而且速度比可能需要的要慢。
如果我考虑在代码中调用 intern() ,我会首先在不使用 intern() 的情况下对其进行分析,然后使用 intern() 对其进行分析以获取内存和速度,并查看哪一个对于更改而言“更差”。
A while ago I intern()ed all of the Strings coming from class files (for a classfile parser). Intern()ing made the program use less memory (won't in this case as others have pointed out) but it did slow the program down significantly (I think it took 4 seconds to parse all of rt.jar and that change put it over 8 seconds). Looking into it at the time (was JDK 1.4 I think) the intern() code is pretty ugly and slower that in probably needs to be.
If I were to consider calling intern() in my code I would first profile it without intern() and then profile it with intern() for both memory and speed and see which one is "worse" for the change.
我已经使用 intern() 来“锁定”。例如,假设我有一个“交易记录”的“存储库”。当我编辑和更新交易时,我想锁定交易;我可能会锁定 tradeId.intern(),这样我就不必担心交易的克隆四处浮动。我不确定大家是否喜欢这个用法。
这假设 id 字段不太可能意外地与另一个域对象的 id 字段发生冲突 - 例如,tradeId 不会与 account_number 发生冲突,人们也可能会这样做,
请参阅 示例
I have used intern() for "locking". For instance, let's say I have a "repository" of "trade records". While I edit and update a trade I want to lock the trade; I might instead lock on the tradeId.intern() so that I don't have to worry about clones of a trade floating around. I am not sure if everybody likes this usage.
This assumes that the id field is unlikely to accidentally collide with the id field of another domain object - a tradeId doesn't happen to collide with account_number for instance, where one might also be doing
see example