0

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.

6
  • "String literals are the same". Commented Nov 19, 2015 at 10:26
  • The compiler is just smart enough to notice that s2 just consists of two literals, and will combine them to the literal my computer. Since this literal exists yet, s1 and s2 are pointing to the same reference of my computer. Commented Nov 19, 2015 at 10:30
  • Constants in Java should be moved to the static content. Commented Nov 19, 2015 at 10:31
  • Really sorry! I have edited the question now. Commented Nov 19, 2015 at 10:33
  • 1
    @swdeveloper biziclop answer actually explains the behavior pretty good. Commented Nov 19, 2015 at 10:36

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

So what I have understood from this is that when we use "+" operator with a string variable (NOT a literal) then new object is created?
@swdeveloper It is slightly more complicated than that, I added a link to the definition of "constant expression",
"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" Great point!
One more thing to clear about "pool of string objects" (because I have seen this phrase in may SO answers and other websites); Is it a fixed memory assigned to string objects? If yes, then how much size is assigned to it and what if there are so many string objects and the size of total string objects is larger than the assigned memory?
@swdeveloper That should really be a separate question: the sizing and behaviour of the string pool differs between Java versions. But you can find a good overview here.
2

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.

Comments

2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.