何时对字符串文字使用 intern()

发布于 2024-08-13 01:33:33 字数 221 浏览 2 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

凝望流年 2024-08-20 01:33:33

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

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

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


JLS 引用:

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:

暮凉 2024-08-20 01:33:33

intern() 与常量字符串文字一起使用是浪费时间,因为文字已经按照 3.10.5。 Java® 语言规范<的字符串文字 /em>。

引用 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

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:

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

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

辞旧 2024-08-20 01:33:33

不久前,我实习了来自类文件的所有字符串(对于类文件解析器)。 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.

淡莣 2024-08-20 01:33:33

我已经使用 intern() 来“锁定”。例如,假设我有一个“交易记录”的“存储库”。当我编辑和更新交易时,我想锁定交易;我可能会锁定 tradeId.intern(),这样我就不必担心交易的克隆四处浮动。我不确定大家是否喜欢这个用法。

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

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

请参阅 示例

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

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

see example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文