7

I'm aware about string pool in JVM and difference between literals and string objects. I know that literals are automatically interned, but what is the purpose of this line then:

public static final String PARAMETER = "value".intern();

On my question I always find a ton of text which explains me the same with emphasis on the difference between literals and objects and mention that literals already interned. Therefore, I'd like to know about underlyings of using that tricky line with intern() over literal.

rook
  • 5,880
  • 4
  • 39
  • 51
  • 9
    I don't remember ever seeing code like that, and it does indeed seem pointless. Where did you see that? – Jon Skeet Jan 21 '14 at 13:53
  • 1
    Literals are interned anyway; seems redundant. Maybe there's an edge case? I'm skeptical it would ever matter in a relevant way, though. I suspect Cult of the Cargo. – Dave Newton Jan 21 '14 at 13:53
  • 8
    I prefer `"value".intern().intern()` just to be sure. – Paul Bellora Jan 21 '14 at 13:55
  • I saw that in the large project, btw good sense Paul) – rook Jan 21 '14 at 13:58
  • @rook - There's no purpose... String literals are interned automatically.. – TheLostMind Jan 21 '14 at 14:00
  • possible duplicate of [Are all compile-time constants inlined?](http://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlined) – Marko Topolnik Jan 21 '14 at 14:03
  • Note that I disagree with @Marko about this being a duplicate - the questions are closely related by they are not duplicates IMO. – Duncan Jones Jan 21 '14 at 14:09
  • 3
    possible duplicate of [When to use intern() on String literals](http://stackoverflow.com/questions/1833581/when-to-use-intern-on-string-literals) – Raedwald Jan 21 '14 at 14:21
  • @MarkoTopolnik Note that an excellent duplicate has been found (by Raedwald) - you may wish to withdraw your close vote to ensure we get a "clean" close here? – Duncan Jones Jan 21 '14 at 14:29

5 Answers5

13

The main benefit of that type of code is to prevent compile-time constants from being inlined.

For instance, suppose you have a constant in one class and you have many other classes refer to that constant. Normally if you change the constant value, you'd need to recompile all the classes involved. Using intern() on the field will prevent inlining of the constant and means it would be sufficient to recompile just your constant class. In theory this approach would have inferior performance, although I have no idea how significant that might be.

This SO question covers the same topic and is a useful read.

Community
  • 1
  • 1
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • 1
    That's an excellent reference, I have voted to close as a duplicate of it. Even if questions don't match, *answers* do. – Marko Topolnik Jan 21 '14 at 14:04
  • 1
    @MarkoTopolnik Yes, it's a great question. Although I'm personally not in favour of closing as a duplicate unless the *questions* match. – Duncan Jones Jan 21 '14 at 14:04
8

To prevent compile time inlining

The only use case I can think of is to prevent it from being considered as compile time constant, so that it prevents inlining.

Now one reason can be that someone can change the value using Reflection, which will only work if the string is declared like that.

Also it allows you to change the class file containing constant as told by @Duncan in his answer. That is a good reason too.

How does that work?

When you declare String as public static final String CONST = "abc";, then it is a compile time constant and will be inlined in the class using that constant.

class A{
    private void foo(){
        String newString = CONST + someDynamicValue;
    }
}

After compiling this, if you decompile the class you will find

class A{
   private void foo(){
       String newString = "abc" + someDynamicString;
   }
}

But when you declare it with .intern() or any other method, then it cannot be considered as compile time constant and every time the value will be fetched from the class. Java does this to be efficient.

Example from @Marko's comment:

the SWT library uses a similar trick to stop from inlining int constants, and the only reason is to be consistent with respect to upgrading the SWT library

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • The second reason is actually *the* reason to use it :) Especially whenever the constant is inside a JAR dependency. – Marko Topolnik Jan 21 '14 at 14:06
  • @MarkoTopolnik yes true :) I was thinking in the same direction but could not give a proper use case. – Narendra Pathai Jan 21 '14 at 14:11
  • For example, the SWT library uses a similar trick to stop from inlining `int` constants, and the only reason is to be consistent with respect to upgrading the SWT library. – Marko Topolnik Jan 21 '14 at 14:12
1

Java automatically interns String literals. This means that in many cases, the == operator appears to work for Strings in the same way that it does for ints or other primitive values.

Since interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()

Using your example:

String s1 = "Shoaib";
String s2 = "Shoaib";
String s3 = "Shoaib".intern();
String s4 = new String("Shoaib");
String s5 = new String("Shoaib").intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

if ( s1 == s4 ){
    System.out.println("s1 and s4 are same" );  // 3.
}

if ( s1 == s5 ){
    System.out.println("s1 and s5 are same" );  // 4.
}

will return:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

Explaination in simple words:

->In String pooled region if suppose we have "Shoaib" as String whose reference is say 2020

->Now Any object you create by new String("Shoaib") will point to another reference say 3030

->But if you want to assign reference of "Shoaib" in String pooled region to new String("Shoaib") then we use intern() on it.

So above you asked that "value".intern() which doesn't make any sense in case of interning.

Shoaib Chikate
  • 8,665
  • 12
  • 47
  • 70
0

The intern() is used to access reference ID of your String Constant Pool.

It is possible that your variable may contain the same value so, we do not need to allocate it again.

We just use intern() to check it is already in String Constant Pool or not ?

If it is not in pool then just JVM allocate in pool area and return it reference ID & We used to share same data member and benefit is that we use same memory.

Amarnath Balasubramanian
  • 9,300
  • 8
  • 34
  • 62
0

The purpose of this line

public static final String PARAMETER = "value".intern();

is just used to check from string constant pool. If it available then it's return not again added in pool.

Robert
  • 5,278
  • 43
  • 65
  • 115