String Comparison and String Interning in Java

String comparison and String interning in Java

You should almost always use equals. You can be certain that string1 == string2 will work if:

  • You've already made sure you've got distinct values in some other way (e.g. you're using string values fetched from a set, but comparing them for some other reason)
  • You know you're dealing with compile-time string constants
  • You've manually interned the strings yourself

It really doesn't happen very often, in my experience.

Difference between String intern method and normal string creation

The difference is that the initialization way of the variable that decides where to save the variable ;

  1. if it has the same value and same initialization method and initialized using new keyword - it will save it in heap and will save each variable as new object even if it has same value.
  2. if it has the same value and same initialization method and initialized directly - it will reference it in JVM pooled memory .

String Interning Oracle reference .

There are two ways to construct a string: implicit construction by assigning a string literal or explicitly creating a String object via the new operator and constructor. For example

String s1 = "Hello";              // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object

Java has provided a special mechanism for keeping the String literals - in a so-called string common pool. If two string literals have the same contents, they will share the same storage inside the common pool. This approach is adopted to conserve storage for frequently-used strings. On the other hand, String objects created via the new operator and constructor are kept in the heap. Each String object in the heap has its own storage just like any other object .

Sample Image

s1 == s1;         // true, same pointer
s1 == s2; // true, s1 and s1 share storage in common pool
s1 == s3; // true, s3 is assigned same pointer as s1
s1.equals(s3); // true, same contents
s1 == s4; // false, different pointers
s1.equals(s4); // true, same contents
s4 == s5; // false, different pointers in heap
s4.equals(s5); // true, same contents

Important Notes:

  1. In the above example, I used relational equality operator '==' to compare the references of two String objects. This is done to demonstrate the differences between string literals sharing storage in the common pool and String objects created in the heap. It is a logical error to use (str1 == str2) in your program to compare the contents of two Strings.
  2. String can be created by directly assigning a String literal which is shared in a common pool. It is uncommon and not recommended to use the new operator to construct a String object in the heap.

Comparing two equal Strings after intern() method

Doing this str1.intern() is bringing nothing to your try...
Since str1 is a literal string (it will be inmediatly placed in the string pool), and you are comparing it against the str2 which is allocated on the Heap...

therefore

System.out.println(str1.intern() == str2); 

will print false, you are comparing the reference of a string in the stirng pool vs a string on the heap...

String + int compare with same String + int in java?

Strings should be compared using the equals method. == compares identity.

"X=" + x == "X=" + x creates two separate string instances, and while the contents are equal, their identities are not.

"X=10" == "X=10" is true because of string interning. The compiler encounters two string literals with the same contents, and decides that the two occurrences point to the same String object, thus they have the same identity.

"Y=" + y == "Y=" + y is true because y is a constant expression, and the compiler decides that the string and the int can be concatenated at compile time, yielding two equal strings. Effectively, it is as if "Y=10" == "Y=10" were written.

java string concatenation and interning

The first part of your question is simple: Java compiler treats concatenation of multiple string literals as a single string literal, i.e.

"I Love" + " Java"

and

"I Love Java"

are two identical string literals, which get properly interned.

The same interning behavior does not apply to += operation on strings, so b1 and b2 are actually constructed at run-time.

The second part is trickier. Recall that b1.intern() may return b1 or some other String object that is equal to it. When you keep a1 and a2, you get a1 back from the call to b1.intern(). When you comment out a1 and a2, there is no existing copy to be returned, so b1.intern() gives you back b1 itself.

When should we use intern method of String on String literals

Java automatically interns String literals. This means that in many cases, the == operator appears to work for Strings in the same way that it does for ints or other primitive values.

Since interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()

Using your example:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();

if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}

if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}

if ( s1 == s4 ){
System.out.println("s1 and s4 are same" ); // 3.
}

if ( s1 == s5 ){
System.out.println("s1 and s5 are same" ); // 4.
}

will return:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

In all the cases besides of s4 variable, a value for which was explicitly created using new operator and where intern method was not used on it's result, it is a single immutable instance that's being returned JVM's string constant pool.

Refer to JavaTechniques "String Equality and Interning" for more information.



Related Topics



Leave a reply



Submit