When to use intern() on String literals

我是研究僧i 提交于 2019-11-27 03:23:55
kdgregory

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:

pjp

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

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!