Apr 22, 2016

Difference between creating string object via string literal and new String

If you are a Java programmer (which should be the case if you are reading this article), you will know the importance of  knowledge of Strings. Because of their wide usage, handling of Strings become very important. This is also one among the hot topic for interview, specially at the initial stage of your carrier.

In Java, we have two ways of creating String objects, using String literal and creating new String object and this article aims at providing the difference between the 2 options.

  • Using the new() operator. For example,
    String str1 = new String("Java");
     
  • Using a string literal or constant expression. For example,
    String str2 ="Java";
    
    String str3 ="Ja" + "va";
     
     
    
    

Both expression gives you String object, but there is subtle difference between the two. In case of new() operator, a new object is created every time in the heap memory. On the other hand, if the string object is created using String literal then an existing object is returned from String pool, if it exists or otherwise a new string object is created and put in string pool for future re-use.

String pool is a cache of String objects in Perm gen space (which is now moved to heap space in Java7). Each time a string literal is created, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. This not only increases the performance but also decreases memory overhead while string creation. Since strings are immutable, therefore Java can make this optimization without fear of data corruption.

See below example,

public class Example1 {

    public static void main(String[] args) {
 String str1 = "Java";
 String str2 = "Java";
 System.out.println("----- Creating strings str1 & str2 using string literal -----");
 System.out.println("str1 == str2 is " + (str1 == str2));
 System.out.println("str1.equals(str2) is " + str1.equals(str2));

 String str3 = new String("Java");
 String str4 = new String("Java");
 System.out.println("----- Creating strings str3 & str4 using new operator -----");
 System.out.println("str3 == str4 is " + (str3 == str4));
 System.out.println("str3.equals(str4) is " + str3.equals(str4));

 String str5 = "Jav" + "a";
 String str6 = "Ja" + "va";
 System.out.println("----- Creating strings str5 & str6 using string constant expression -----");
 System.out.println("str5 == str6 is " + (str5 == str6));
 System.out.println("str5.equals(str6) is " + str5.equals(str6));

 String s = "a";
 String str7 = "Jav" + s;
 String str8 = "Ja" + "va";
 System.out.println("----- String str7 is computed at runtime -----");
 System.out.println("----- Creating string str8 using string constant expression -----");
 System.out.println("str7 == str8 is " + (str7 == str8));
 System.out.println("str7.equals(str8) is " + str7.equals(str8));
    }
}


Output:

----- Creating strings str1 & str2 using string literal -----
str1 == str2 is true
str1.equals(str2) is true
----- Creating strings str3 & str4 using new operator -----
str3 == str4 is false
str3.equals(str4) is true
----- Creating strings str5 & str6 using string constant expression -----
str5 == str6 is true
str5.equals(str6) is true
----- String str7 is computed at runtime -----
----- Creating string str8 using string constant expression -----
str7 == str8 is false
str7.equals(str8) is true

Lets now understand the above class 'Example1',

We have created 2 strings 'str1' and 'str2' using string literals. Since the strings refer to the same string object in the string pool, therefore both '==' and  'equals' return 'true'.

Strings 'str3' and 'str4' are created using new() string object. So, a new string object is created for both of them even if the same exist in the string pool. Since both the strings refer to different string objects, therefore '==' returns 'false' whereas 'equals' return 'true'.

Strings 'str5' and 'str6' are created using string constants. Strings computed by constant expressions are computed at compile time and treated as if they were literals, so they point to the same String in the string pool. Therefore both '==' and  'equals' return 'true'.

String 'str7' is computed by concatenation at run time and thus considered as newly created string. Therefore '==' returns 'false' and 'equals' return 'true' on comparison with string literal 'str8.

In short, any string created with new() or computed at run time refers to a new string object instead of string literals present in the string pool. So, '==' will always returns 'false' on comparison with any other string. That's why it is always suggested to compare two String object using equals method and instead of  == operator, because you never know which one is coming from pool and which one is created using new() operator.

intern() method 

As we now know that String objects created with the new operator do not refer to objects in the string pool. But they can be made to refer string pool objects by using String's intern() method. The java.lang.String.intern() returns an interned String, i.e. one that has an entry in the global String pool. If the String is not already in the global String pool, then it will be added.

Lets now see an example using intern() method,

public class Example2 {

    public static void main(String[] args) {
        String s1 = "Java";
        String s2 = new StringBuffer("Ja").append("va").toString();
        String s3 = s2.intern();
        System.out.println("----- Creating string str1 using string literal -----");
        System.out.println("----- Creating string str2 using new operator -----");
        System.out.println("----- Creating string str3 using intern method -----");
        System.out.println("s1 == s2 is " + (s1 == s2));
        System.out.println("s1 == s3 is " + (s1 == s3));
    }
}

Output:

----- Creating string str1 using string literal -----
----- Creating string str2 using new operator -----
----- Creating string str3 using intern method -----
s1 == s2 is false
s1 == s3 is true

There is always a reference to String objects in string literal pool, therefore, the string objects in the string literal pool are not eligible for garbage collection.

That's all! Hope you liked the article. Connect at +Java Territory to stay updated.

0 comments:

Post a Comment