swdeveloper
swdeveloper

Reputation: 918

Confusion in String concatenation operator "+" in Java

According to my knowledge, we cannot use == operators to compare String values in Java. So I wrote the following code:

public class Test {
  public static void main(String[] args) {

    String s1 = "My Computer";
    String s2 = "My" + " Computer";

    System.out.println(s1 == s2);
  }
}

And I was expecting the result to be false because these are two different objects having assigned different memory locations (please correct me in this regard if I am wrong ). But when I executed the code, the output was true.

Then I changed the value of s2 as:

String str = "My";
String s2 = str + " Computer";      //instead of "My" + " Computer"

And then when I executed the code, the output was false.

Now I cannot understand the difference in these two statements, although I have used + (not the concat() method) in both statements. Can anyone explain, please.

Upvotes: 0

Views: 148

Answers (3)

biziclop
biziclop

Reputation: 49714

What trips you up is this part of the specification:

The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).

So when you concatenate a string constant to another string constant, that counts as a constant expression and therefore will be evaluated at compile time and replaced with the string constant "My Computer".

You can verify this by running javap -c on the compiled class.

public class Test {

    public static void main(String[] args) {

        String s1 = "My Computer";
        String s2 = "My" + " Computer";
        String s3 = "My";
        String s4 = s3 + " Computer";

        System.out.println(s1 == s2); //true
        System.out.println(s1 == s4); //false
    }
}

Which compiles to:

  public static void main(java.lang.String[]);
    Code:
       // s1 = "My Computer"
       0: ldc           #2                  // String My Computer
       2: astore_1

       // s2 = "My" + " Computer"
       3: ldc           #2                  // String My Computer
       5: astore_2

       // s3 = "My"
       6: ldc           #3                  // String My
       8: astore_3

       // s4 = s3 + " Computer"
       9: new           #4                  // class java/lang/StringBuilder
      12: dup
      13: invokespecial #5                  // Method java/lang/StringBuilder."<
init>":()V
      16: aload_3
      17: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      20: ldc           #7                  // String  Computer
      22: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      25: invokevirtual #8                  // Method java/lang/StringBuilder.to
String:()Ljava/lang/String;
      28: astore        4

      ... the rest of the code omitted 

As you can see, the first two assignments (to s1 and s2) load exactly the same constant (#2), and therefore use the same object. Whereas the assignment to s4 is not defined as a constant expression (even though a sufficiently clever compiler could figure it out, it is not allowed to), and therefore you get the whole "create a StringBuilder, append the strings to it, convert the result to a new string" process.

As an interesting aside, if in the code above you add the final modifier to s3, that makes s3 + " Computer" a constant expression again, and both comparisons will print true.

And as no doubt you already know, your code's correctness mustn't rely on all of this, but it's a fun thing to know.

Upvotes: 2

Sauhard Gupta
Sauhard Gupta

Reputation: 219

There is a silly error in your test cases. String s2 = s1 + " Computer"; would assign s2 the string "My Computer Computer", not "My Computer".

For how to do String comparison Java, visit this link.

Why String is immutable in Java - an article explaining why instances of the String class in Java can not be modified. Read this for clarity.

Upvotes: 2

Emerson Cod
Emerson Cod

Reputation: 2090

Java uses a pool for String objects - it tries to be smart. This means that when the compiler can figure out that you actually have the same object, even the == on two seemingly different objects return true.

Nevertheless, it should be avoided to compare objects via == if you like to compare the content, as this only compares the object reference. For content comparison equals should be used.

Upvotes: 2

Related Questions