-6
public class StringTest {

    public static void main(String[] args) {
        String s1 = "java";
        String s2 = "ja" + "va";

        String s3 = "ja";
        String s4 = s3 + "va";

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

First System.out.println(...); statement as expected outputs true, but why is second statement showing false as output?

I want to know which string is created in pool area and which in non-pool area of pool.

Vy Do
  • 46,709
  • 59
  • 215
  • 313
Aamir
  • 2,380
  • 3
  • 24
  • 54

3 Answers3

1

Use .equals() to compare String objects.

{
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s4));
}

This is because the == operator on Object (here String) checks for same object references, for String equality you must use .equals().

The + concatenation operator is effectively compiled down from:

a + b (a, b type String)

to:

new StringBuffer(a).append(b) (loading String in the common pool)

On the other hand, in the following code:

String s1 = "java";
String s2 = "ja" + "va";
// "ja" appends to "va". As the compiler optimization pass realizes
// that "ja" + "va" is literal "java", it burns down the two strings into
// the same literal as s1.

String s3 = "ja";
String s4 = s3 + "va";
// s3 appends to "va". As the compiler cannot effectively study the literal,
// It is allowed to be concatenated at run-time. This allows "java" to be
// created from the heap, instead of from the common pool.
Unihedron
  • 10,902
  • 13
  • 62
  • 72
1

String literals in Java are interned (put into a cached string pool). Literals is when they're written purely in the code with " " around them.

When an entire expression of string literals (in your case concatenations) can be evaluated at compile time, such strings are also interned.

You intern "java" and "ja". The compiler could have been smart enough to see that s3 does not change between declaration+initialization but it does not, because it's not final.

Declaring s3 to be final will yield true for 2nd SOP. So will adding s4 = s4.intern(); before printing.

Edit: you asked "What exactly is s4 = s4.intern()":

s4.intern() will look through the pool of cached strings and return the cached string that is equal to s4 from the pool. Then it is assigned to s4 again. So: it replaces the s4 reference with the cached version if it exists. [Sideeffect: if it wasn't in the pool, it will be added and the reference is unchanged].

Xabster
  • 3,710
  • 15
  • 21
0

== tests for reference equality, while .equals() tests for value equality.

Only use == when you have a guarantee that the same object will be used for both.

For more information: How do I compare strings in Java? It also links to an article about string interning which is a mechanism of storing only one copy of each distinct string.

Chad
  • 2,041
  • 6
  • 25
  • 39
  • is it correct to say that String concatenation occurs at compile-time, but when references are involved like in my second SOP, then its a runtime situation and that is why false is the output. – Aamir Aug 10 '14 at 06:11
  • I cannot comment with enough accuracy, however you may have a point. The compiler may be optimizing string concatenations, such that in your first case, it will be the same object, while in your second case, it won't – Chad Aug 10 '14 at 06:52