简体   繁体   中英

Why constant strings use intern()?

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.

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.

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

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM