Prashant Pandey
Prashant Pandey

Reputation: 4642

Are runtime Strings interned?

Here's my code:

public class StringExperimenter {
    public static void main(String[] args) {
        String s1 = "This is" + "limafoxtrottango";
        String s2 = "This is" + getName();
        String s3 = "This is" + getName();
        System.out.println(s1 == s2);  // prints false
        System.out.println(s3 == s2);  // prints false
    }

    private static String getName() {
        return "limafoxtrotango";
    }
}

Now, I understand that s1 is evaluated by the compiler at compile-time and it is then interned.

But, what about s2 and s3? Both of these are created at runtime. So, are two different strings created? Do these strings go to the constant string pool?

Upvotes: 1

Views: 163

Answers (3)

Zabuzard
Zabuzard

Reputation: 25903

s1 is completely interned, i.e.

This islimafoxtrottango

as the string concatenation happens at compile-time.

The other two require a method call, only the intermediate strings are interned. The concatenation is not, as it happens at runtime.

You also observed that already, as

System.out.println(s1 == s2);    //prints false
System.out.println(s3 == s2);    //prints false

would otherwise print true.


You can check the JLS (Java Language Specification) for details on this behavior, every valid Java implementation must do it exactly that way.

From JLS§15.28 about Constant Expressions:

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

The following list contains more or less:

  • literals
  • operators like +
  • constant variables

Importantly, it does not list any method calls, even if they return a constant value.

It also states that:

Constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.

Upvotes: 4

tbsalling
tbsalling

Reputation: 4545

If you compile your class from the command line like this:

javac.exe -g StringExperimenter.java

And then use javap.exe -v StringExperimenter.class to study the resulting class file, then you will see, that the following byte code is generated:

...  
public static void main(java.lang.String...);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
    Code:
      stack=3, locals=4, args_size=1
         0: ldc           #2                  // String This islimafoxtrottango
         2: astore_1
         3: new           #3                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: ldc           #5                  // String This is
        12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder
        15: invokestatic  #7                  // Method getName:()Ljava/lang/String;
        18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder
        21: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        24: astore_2
        25: new           #3                  // class java/lang/StringBuilder
        28: dup
        29: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        32: ldc           #5                  // String This is
        34: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder
        37: invokestatic  #7                  // Method getName:()Ljava/lang/String;
        40: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder
        43: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        46: astore_3
        47: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
        50: aload_1
        51: aload_2
        52: if_acmpne     59
        55: iconst_1
        56: goto          60
        59: iconst_0
        60: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
        63: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
        66: aload_3
        67: aload_2
        68: if_acmpne     75
        71: iconst_1
        72: goto          76
        75: iconst_0
        76: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
        79: return
...  

Based on this, I would say that s1 is interned whereas s2 and s3 are computed (using StringBuilder) at runtime.

Upvotes: 2

Chetan Joshi
Chetan Joshi

Reputation: 5711

As Conspect of String is immutable in java. Above result are true. Whenever we append something in one string by concating creates a new reference in the String intern pool.

So if compare all above 3 Strings using equals methods its return True but false if compare using == operator.

Upvotes: 1

Related Questions