views:

313

answers:

3

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?

+13  A: 

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 of the JLS.

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.

pjp
The JLS talks about outcomes, but it's not clear whether this folding happens at compile-time, or whether it's just that there must be no observable difference between compile-time folding and concatenate-and-then-intern at run-time. Byte code inspection would answer whether two string concatenated literals become one in the class file.
seh
+15  A: 

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:

kdgregory
Now that's what i'd call a trick
pjp
I just confirmed this experimentally, but is there a JLS citation?
jleedev
This is similar to http://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlined
pjp
I guess people shouldn't go changing the value of constants which are visible to other classes.
pjp
that's a nice trick to know. but it looks quite weird. any better trick to do the same thing?
irreputable
alternative A: call toString() on the string. this could be faster than intern()? alternative B: a utility method: String str(String s){ return s; } the method should be commented for its purpose - breaking compile time constant, so readers understand what's going on when they see: static final String ABC = str("xxx");
irreputable
A: 

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.

TofuBeer
wow... and the down votes for accurate info were for what? Is the information provided wrong?
TofuBeer
indeed pjp was pretty generous with downvotes on this question
Gregory Pakosz
I don't care about the down votes... just the reason for them :-)
TofuBeer