7
import java.util.*;
import java.lang.*;
import java.io.*;    

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

      String a="hello"+"world";  //line 1
      String b="hello";
      String c="world";
      String d=b+c;
      String e="helloworld";
      System.out.println(e==a);
      System.out.println(a==d);
     }
}

output:

true

false

From this discussion How does the String class override the + operator? I understood that 'a' and 'e' will refer to same String literal object.

Could anybody please tell

  1. Why a and d are not referring to same string literal object?

  2. How many objects were creating in line 1

Community
  • 1
  • 1
nantitv
  • 3,539
  • 4
  • 38
  • 61

5 Answers5

14

From JLS 4.3.3. The Class String

The string concatenation operator + (§15.18.1) implicitly creates a new String object when the result is not a compile-time constant expression (§15.28).

Because literal value of a is "helloworld" and literal value of d is a reference object of b + c that is not a literal as from above JLS 4.3.3.

From JLS 3.10.5 String Literals

A string literal consists of zero or more characters enclosed in double quotes.

From 15.28. Constant Expressions

A compile-time 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:

  • Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

If you want to make System.out.println(a==d); true use final keyword see below code:

  String a="hello"+"world";  //line 1
  final String b="hello"; // now b is a literal
  final String c="world";// now c is a literal
  String d=b+c;
  String e="helloworld";
  System.out.println(e==a);
  System.out.println(a==d);// now it will be true because both are literals.

Answer for comment:
How many objects were creating in line 1: Answer is 3
String a="hello"+"world";

1st literal object hello
2nd literal object world
3rd literal object "hello"+"world" == "helloworld"

Community
  • 1
  • 1
Sumit Singh
  • 15,743
  • 6
  • 59
  • 89
  • @SumitSingh Thank you. To get more clarification -> Is the internal representation of line 1 is new StringBuilder("hello").append("world").toString() ? – nantitv Apr 14 '15 at 11:41
  • From your latest update to the answer I guess internal representation of line 1 is not "new StringBuilder("hello").append("world").toString()" – nantitv Apr 14 '15 at 11:42
2

The == sign checks if references to variables are the same. To check if any object is equal to other use Object.equals(Object o) method like this:

e.equals(a);
novy1234
  • 333
  • 1
  • 11
1

The == operator checks reference equality, not object equality. In your example two String instances with content "helloworld" have been created. The variables a and e refer to the same instance (see below), while a and d do not. String equality can be checked with the equals() method, that is a.equals(d) is true.

The reason that a and e refer to the same instance is that String constants are interned. Every time a string constant, like "helloworld", is encountered, it is checked if such a constant was already encountered, and if it has, the old String instance is returned instead of creating a new one. Although "hello" + "world" does not look like a String constant, it is optimized to a String constant by the Java compiler, and therefore it is interned like e, which is why a == e is true. In constrast, b + c is not optimized to a constant, which is why a == d is false (however, a.equals(d) would be true).

Hoopje
  • 12,677
  • 8
  • 34
  • 50
1

1) It's because String objects are immutable. Once you create a String object and assign it a value, it has the same value forever that cannot be changed. Thus there is always created a new String object when you make any operations with it (for example joining).

In heap there is a special part of it that serves as a pool for String constants. If the compiler encounters a String literal, it first looks into this part of memory whether identical object (String) already exists. If it does, it assigns a reference to this already existing object (String) instead of creating a new one. (This is the reason why Strings are immutable, so no one can change it. Because if several references would point to this String and one of them would change its value, it would create a mess.)

Now let's take a look what is going on in this code snippet and try to find the answer to both of your questions at once.

(1) String a="hello"+"world";  //line 1
(2) String b="hello"; // now b is a literal
(3) String c="world";
(4) String d=b+c;
(5) String e="helloworld";
(6) System.out.println(e==a);
(7) System.out.println(a==d);

(1) First there is created a reference value a that points to type String. Then there is created literal "hello" in this special pool in heap mentioned earlier (1st String object). Then there is created literal "world" in the pool (2nd String object). Then, since Strings are immutable, there is created another literal in this pool- "helloworld" and it is assigned to this reference variable a (3rd String object - this is the answer to your question Nr. 2).

(2) Literals "hello" and "world" created in (1) were created in pool and weren't assigned to any reference value, but they stil exist in this pool. In this line there is reference variable of type String b created and it is assigned to this literal "hello" existing in pool.

(3) same as (2)

(4) Created reference value of type String d. Although there already IS a String literal in this special heap part (pool) with value "helloworld", a new String object with value "helloworld" is created in heap - that means in non-pool part of heap. Therefore you have two different objects of type String with value "helloworld" (One in a pool and the other in a non-pool part of heap). If you now compare with == operator reference values a and d, both of them point to different objects (with same value though, so method equals would return true).

(5) Created reference value e of type String. In pool part of heap there already is a String "helloworld" (we created it in (1) and pointed it to reference variable a) so the reference variable e is assigned to this object. And points to same place as a. Therefore if you compare references a == e you get true. The same would be for method equals

(6) and (7) were explained in previous points

TLDR:

1) because it is not the same object

2) 3

WrongRhyme
  • 166
  • 1
  • 1
  • 7
0

The == operator checks if the two objects refer to the same place in memory.

The a = "hello" + "world;" evaluates to the literal "helloworld" and e="helloworld" is given. They refer to the same memory location. Hence the expression e==a evaluates to true.

The expression d=b+c also evaluates to "helloworld" but this result is stored at a different location. It does not refer to the same object. Hence the expression a==d evaluates to false.

Using a.equals(d) will output true because equals() checks the contents of the 2 objects.

Amita
  • 944
  • 1
  • 8
  • 20