How Java String Pool Working? [duplicate] - java

What is String Interning in Java, when I should use it, and why?

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()
Basically doing String.intern() on a series of strings will ensure that all strings having same contents share same memory. So if you have list of names where 'john' appears 1000 times, by interning you ensure only one 'john' is actually allocated memory.
This can be useful to reduce memory requirements of your program. But be aware that the cache is maintained by JVM in permanent memory pool which is usually limited in size compared to heap so you should not use intern if you don't have too many duplicate values.
More on memory constraints of using intern()
On one hand, it is true that you can remove String duplicates by
internalizing them. The problem is that the internalized strings go to
the Permanent Generation, which is an area of the JVM that is reserved
for non-user objects, like Classes, Methods and other internal JVM
objects. The size of this area is limited, and is usually much smaller
than the heap. Calling intern() on a String has the effect of moving
it out from the heap into the permanent generation, and you risk
running out of PermGen space.
--
From: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html
From JDK 7 (I mean in HotSpot), something has changed.
In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
-- From Java SE 7 Features and Enhancements
Update: Interned strings are stored in main heap from Java 7 onwards. http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes

There are some "catchy interview" questions, such as why you get equals! if you execute the below piece of code.
String s1 = "testString";
String s2 = "testString";
if(s1 == s2) System.out.println("equals!");
If you want to compare Strings you should use equals(). The above will print equals because the testString is already interned for you by the compiler. You can intern the strings yourself using intern method as is shown in previous answers....

JLS
JLS 7 3.10.5 defines it and gives a practical example:
Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
Example 3.10.5-1. String Literals
The program consisting of the compilation unit (§7.3):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
JVMS
JVMS 7 5.1 says says that interning is implemented magically and efficiently with a dedicated CONSTANT_String_info struct (unlike most other objects which have more generic representations):
A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.
The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:
("a" + "b" + "c").intern() == "abc"
To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.
If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.
Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.
Bytecode
Let's decompile some OpenJDK 7 bytecode to see interning in action.
If we decompile:
public class StringPool {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a);
System.out.println(b);
System.out.println(a == c);
}
}
we have on the constant pool:
#2 = String #32 // abc
[...]
#32 = Utf8 abc
and main:
0: ldc #2 // String abc
2: astore_1
3: ldc #2 // String abc
5: astore_2
6: new #3 // class java/lang/String
9: dup
10: ldc #2 // String abc
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne 42
38: iconst_1
39: goto 43
42: iconst_0
43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
Note how:
0 and 3: the same ldc #2 constant is loaded (the literals)
12: a new string instance is created (with #2 as argument)
35: a and c are compared as regular objects with if_acmpne
The representation of constant strings is quite magic on the bytecode:
it has a dedicated CONSTANT_String_info structure, unlike regular objects (e.g. new String)
the struct points to a CONSTANT_Utf8_info Structure that contains the data. That is the only necessary data to represent the string.
and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by ldc.
I have done similar tests for fields, and:
static final String s = "abc" points to the constant table through the ConstantValue Attribute
non-final fields don't have that attribute, but can still be initialized with ldc
Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.
Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no CONSTANT_String_info analogue).

Update for Java 8 or plus.
In Java 8, PermGen (Permanent Generation) space is removed and replaced by Meta Space. The String pool memory is moved to the heap of JVM.
Compared with Java 7, the String pool size is increased in the heap. Therefore, you have more space for internalized Strings, but you have less memory for the whole application.
One more thing, you have already known that when comparing 2 (referrences of) objects in Java, '==' is used for comparing the reference of object, 'equals' is used for comparing the contents of object.
Let's check this code:
String value1 = "70";
String value2 = "70";
String value3 = new Integer(70).toString();
Result:
value1 == value2 ---> true
value1 == value3 ---> false
value1.equals(value3) ---> true
value1 == value3.intern() ---> true
That's why you should use 'equals' to compare 2 String objects. And that's is how intern() is useful.

Since strings are objects and since all objects in Java are always stored only in the heap space, all strings are stored in the heap space. However, Java keeps strings created without using the new keyword in a special area of the heap space, which is called "string pool". Java keeps the strings created using the new keyword in the regular heap space.
The purpose of the string pool is to maintain a set of unique strings. Any time you create a new string without using the new keyword, Java checks whether the same string already exists in the string pool. If it does, Java returns a reference to the same String object and if it does not, Java creates a new String object in the string pool and returns its reference. So, for example, if you use the string "hello" twice in your code as shown below, you will get a reference to the same string. We can actually test this theory out by comparing two different reference variables using the == operator as shown in the following code:
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); //prints true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str3); //prints false
System.out.println(str3 == str4); //prints false
== operator is simply checks whether two references point to the same object or not and returns true if they do. In the above code, str2 gets the reference to the same String object which was created earlier. However, str3 and str4 get references to two entirely different String objects. That is why str1 == str2 returns true but str1 == str3 and str3 == str4 return false .
In fact, when you do new String("hello"); two String objects are created instead of just one if this is the first time the string "hello" is used in the anywhere in program - one in the string pool because of the use of a quoted string, and one in the regular heap space because of the use of new keyword.
String pooling is Java's way of saving program memory by avoiding the creation of multiple String objects containing the same value. It is possible to get a string from the string pool for a string created using the new keyword by using String's intern method. It is called "interning" of string objects. For example,
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2.intern(); //get an interned string obj
System.out.println(str1 == str2); //prints false
System.out.println(str1 == str3); //prints true
OCP Java SE 11 Programmer, Deshmukh

String interning is an optimization technique by the compiler. If you have two identical string literals in one compilation unit then the code generated ensures that there is only one string object created for all the instance of that literal(characters enclosed in double quotes) within the assembly.
I am from C# background, so i can explain by giving a example from that:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
output of the following comparisons:
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
Note1:Objects are compared by reference.
Note2:typeof(int).Name is evaluated by reflection method so it does not gets evaluated at compile time. Here these comparisons are made at compile time.
Analysis of the Results:
1) true because they both contain same literal and so the code generated will have only one object referencing "Int32". See Note 1.
2) true because the content of both the value is checked which is same.
3) FALSE because str2 and obj does not have the same literal. See Note 2.

Java interning() method basically makes sure that if String object is present in SCP, If yes then it returns that object and if not then creates that objects in SCP and return its references
for eg: String s1=new String("abc");
String s2="abc";
String s3="abc";
s1==s2// false, because 1 object of s1 is stored in heap and other in scp(but this objects doesn't have explicit reference) and s2 in scp
s2==s3// true
now if we do intern on s1
s1=s1.intern()
//JVM checks if there is any string in the pool with value “abc” is present? Since there is a string object in the pool with value “abc”, its reference is returned.
Notice that we are calling s1 = s1.intern(), so the s1 is now referring to the string pool object having value “abc”.
At this point, all the three string objects are referring to the same object in the string pool. Hence s1==s2 is returning true now.

By using heap object reference, if we want to corresponding SCP object reference we should go for intern() method.
Example :
class InternDemo
{
public static void main(String[] args)
{
String s1=new String("smith");
String s2=s1.intern();
String s3="smith";
System.out.println(s2==s3);//true
}
}
intern flow chart

Related

usage of direct strings vs creating a variable in local method

I'm trying to understand is there any difference (performance/best programming practice..etc) between using a direct string vs creating a temporary variable in side a method and used it exactly once. Here is an example
Class Sample {
public boolean compareString(String str){
String test = "Test";
return test.equalsIgnoreCase(str);
vs
return "Test".equalsIgnoreCase(str);
}
}
In my opinion, both are the same. Instead of creating a variable, one can directly use it. Please let me if there are any other differences and which one is preferred?
No difference, because string literals (like "one", "two") are stored into String Pool and reused.
From your example:
String test = "Test";
// "Test" - string literal is stored in the StringPool
// test - reference to string literal "Test" from StringPool
return test.equalsIgnoreCase(str);
return "Test".equalsIgnoreCase(str);
// in both cases you use the same string literal stored in StringPool
P.S.
String str = new String("abc");
// "abc" - string literal is created (or reused) and stored in StringPool
// new String() - string object is stored in heap and contains (separate copy) of string literal "abc"
// str - reference to the string object in heap
In case you want to get a refernce to the string from StringPool:
String str1 = str.intern();
// str1 - reference to the string literal from the String Pool
Here is the difference.
String str = null;
String test = "Test";
boolean a = test.equalsIgnoreCase(str);
boolean b = "Test".equalsIgnoreCase(str);
The bytecode
2 ldc <String "Test"> [16] // push the constant on stack
4 astore_2 [test] // stores in internal list
5 aload_2 [test] // retrieves constant, pushes on stack
6 aload_1 [str] // target of comparison
7 invokevirtual java.lang.String.equalsIgnoreCase(java.lang.String) : boolean [18]
10 istore_3 [a] // store boolean result
11 ldc <String "Test"> [16] // push the constant on stack
13 aload_1 [str] // target of comparison
14 invokevirtual java.lang.String.equalsIgnoreCase(java.lang.String) : boolean [18]
17 istore 4 [b] // store boolean result
I was looking for any differences (peformance/programming practice.. etc) between 2 approaches and found that there are no differences.
2nd approach is better in best programming practice (it make sense to create a temporary variables if it is used in other places with in that method).

What does String intern() method do? [duplicate]

What is String Interning in Java, when I should use it, and why?
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()
Basically doing String.intern() on a series of strings will ensure that all strings having same contents share same memory. So if you have list of names where 'john' appears 1000 times, by interning you ensure only one 'john' is actually allocated memory.
This can be useful to reduce memory requirements of your program. But be aware that the cache is maintained by JVM in permanent memory pool which is usually limited in size compared to heap so you should not use intern if you don't have too many duplicate values.
More on memory constraints of using intern()
On one hand, it is true that you can remove String duplicates by
internalizing them. The problem is that the internalized strings go to
the Permanent Generation, which is an area of the JVM that is reserved
for non-user objects, like Classes, Methods and other internal JVM
objects. The size of this area is limited, and is usually much smaller
than the heap. Calling intern() on a String has the effect of moving
it out from the heap into the permanent generation, and you risk
running out of PermGen space.
--
From: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html
From JDK 7 (I mean in HotSpot), something has changed.
In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
-- From Java SE 7 Features and Enhancements
Update: Interned strings are stored in main heap from Java 7 onwards. http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes
There are some "catchy interview" questions, such as why you get equals! if you execute the below piece of code.
String s1 = "testString";
String s2 = "testString";
if(s1 == s2) System.out.println("equals!");
If you want to compare Strings you should use equals(). The above will print equals because the testString is already interned for you by the compiler. You can intern the strings yourself using intern method as is shown in previous answers....
JLS
JLS 7 3.10.5 defines it and gives a practical example:
Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
Example 3.10.5-1. String Literals
The program consisting of the compilation unit (§7.3):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
JVMS
JVMS 7 5.1 says says that interning is implemented magically and efficiently with a dedicated CONSTANT_String_info struct (unlike most other objects which have more generic representations):
A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.
The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:
("a" + "b" + "c").intern() == "abc"
To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.
If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.
Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.
Bytecode
Let's decompile some OpenJDK 7 bytecode to see interning in action.
If we decompile:
public class StringPool {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a);
System.out.println(b);
System.out.println(a == c);
}
}
we have on the constant pool:
#2 = String #32 // abc
[...]
#32 = Utf8 abc
and main:
0: ldc #2 // String abc
2: astore_1
3: ldc #2 // String abc
5: astore_2
6: new #3 // class java/lang/String
9: dup
10: ldc #2 // String abc
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne 42
38: iconst_1
39: goto 43
42: iconst_0
43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
Note how:
0 and 3: the same ldc #2 constant is loaded (the literals)
12: a new string instance is created (with #2 as argument)
35: a and c are compared as regular objects with if_acmpne
The representation of constant strings is quite magic on the bytecode:
it has a dedicated CONSTANT_String_info structure, unlike regular objects (e.g. new String)
the struct points to a CONSTANT_Utf8_info Structure that contains the data. That is the only necessary data to represent the string.
and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by ldc.
I have done similar tests for fields, and:
static final String s = "abc" points to the constant table through the ConstantValue Attribute
non-final fields don't have that attribute, but can still be initialized with ldc
Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.
Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no CONSTANT_String_info analogue).
Update for Java 8 or plus.
In Java 8, PermGen (Permanent Generation) space is removed and replaced by Meta Space. The String pool memory is moved to the heap of JVM.
Compared with Java 7, the String pool size is increased in the heap. Therefore, you have more space for internalized Strings, but you have less memory for the whole application.
One more thing, you have already known that when comparing 2 (referrences of) objects in Java, '==' is used for comparing the reference of object, 'equals' is used for comparing the contents of object.
Let's check this code:
String value1 = "70";
String value2 = "70";
String value3 = new Integer(70).toString();
Result:
value1 == value2 ---> true
value1 == value3 ---> false
value1.equals(value3) ---> true
value1 == value3.intern() ---> true
That's why you should use 'equals' to compare 2 String objects. And that's is how intern() is useful.
Since strings are objects and since all objects in Java are always stored only in the heap space, all strings are stored in the heap space. However, Java keeps strings created without using the new keyword in a special area of the heap space, which is called "string pool". Java keeps the strings created using the new keyword in the regular heap space.
The purpose of the string pool is to maintain a set of unique strings. Any time you create a new string without using the new keyword, Java checks whether the same string already exists in the string pool. If it does, Java returns a reference to the same String object and if it does not, Java creates a new String object in the string pool and returns its reference. So, for example, if you use the string "hello" twice in your code as shown below, you will get a reference to the same string. We can actually test this theory out by comparing two different reference variables using the == operator as shown in the following code:
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); //prints true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str3); //prints false
System.out.println(str3 == str4); //prints false
== operator is simply checks whether two references point to the same object or not and returns true if they do. In the above code, str2 gets the reference to the same String object which was created earlier. However, str3 and str4 get references to two entirely different String objects. That is why str1 == str2 returns true but str1 == str3 and str3 == str4 return false .
In fact, when you do new String("hello"); two String objects are created instead of just one if this is the first time the string "hello" is used in the anywhere in program - one in the string pool because of the use of a quoted string, and one in the regular heap space because of the use of new keyword.
String pooling is Java's way of saving program memory by avoiding the creation of multiple String objects containing the same value. It is possible to get a string from the string pool for a string created using the new keyword by using String's intern method. It is called "interning" of string objects. For example,
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2.intern(); //get an interned string obj
System.out.println(str1 == str2); //prints false
System.out.println(str1 == str3); //prints true
OCP Java SE 11 Programmer, Deshmukh
String interning is an optimization technique by the compiler. If you have two identical string literals in one compilation unit then the code generated ensures that there is only one string object created for all the instance of that literal(characters enclosed in double quotes) within the assembly.
I am from C# background, so i can explain by giving a example from that:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
output of the following comparisons:
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
Note1:Objects are compared by reference.
Note2:typeof(int).Name is evaluated by reflection method so it does not gets evaluated at compile time. Here these comparisons are made at compile time.
Analysis of the Results:
1) true because they both contain same literal and so the code generated will have only one object referencing "Int32". See Note 1.
2) true because the content of both the value is checked which is same.
3) FALSE because str2 and obj does not have the same literal. See Note 2.
Java interning() method basically makes sure that if String object is present in SCP, If yes then it returns that object and if not then creates that objects in SCP and return its references
for eg: String s1=new String("abc");
String s2="abc";
String s3="abc";
s1==s2// false, because 1 object of s1 is stored in heap and other in scp(but this objects doesn't have explicit reference) and s2 in scp
s2==s3// true
now if we do intern on s1
s1=s1.intern()
//JVM checks if there is any string in the pool with value “abc” is present? Since there is a string object in the pool with value “abc”, its reference is returned.
Notice that we are calling s1 = s1.intern(), so the s1 is now referring to the string pool object having value “abc”.
At this point, all the three string objects are referring to the same object in the string pool. Hence s1==s2 is returning true now.
By using heap object reference, if we want to corresponding SCP object reference we should go for intern() method.
Example :
class InternDemo
{
public static void main(String[] args)
{
String s1=new String("smith");
String s2=s1.intern();
String s3="smith";
System.out.println(s2==s3);//true
}
}
intern flow chart

How many String objects would be created when concatenating multiple Strings?

I was asked in an interview about the number of objects that will be created on the given problem:
String str1 = "First";
String str2 = "Second";
String str3 = "Third";
String str4 = str1 + str2 + str3;
I answered that there would be 6 objects created in the string pool.
3 would be for each of the three variables.
1 would be for str1 + str2 (let's say str).
1 would be for str2 + str3.
1 would be for the str + str3 (str = str1 + str2).
Is the answer I gave correct? If not, what is the correct answer?
Any answer to your question will depend on the JVM implementation and the Java version currently being used. I think it's an unreasonable question to ask in an interview.
Java 8
On my machine, with Java 1.8.0_201, your snippet results in this bytecode
L0
LINENUMBER 13 L0
LDC "First"
ASTORE 1
L1
LINENUMBER 14 L1
LDC "Second"
ASTORE 2
L2
LINENUMBER 15 L2
LDC "Third"
ASTORE 3
L3
LINENUMBER 16 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 3
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 4
which proves that 5 objects are being created (3 String literals*, 1 StringBuilder, 1 dynamically produced String instance by StringBuilder#toString).
Java 12
On my machine, with Java 12.0.2, the bytecode is
// identical to the bytecode above
L3
LINENUMBER 16 L3
ALOAD 1
ALOAD 2
ALOAD 3
INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
// arguments:
"\u0001\u0001\u0001"
]
ASTORE 4
which magically changes "the correct answer" to 4 objects since there is no intermediate StringBuilder involved.
*Let's dig a bit deeper.
12.5. Creation of New Class Instances
A new class instance may be implicitly created in the following situations:
Loading of a class or interface that contains a string literal (§3.10.5) may create a new String object to represent the literal. (This will not occur if a string denoting the same sequence of Unicode code points has previously been interned.)
In other words, when you start an application, there are already objects in the String pool. You barely know what they are and where they come from (unless you scan all loaded classes for all literals they contain).
The java.lang.String class will be undoubtedly loaded as an essential JVM class, meaning all its literals will be created and placed into the pool.
Let's take a randomly selected snippet from the source code of String, pick a couple of literals from it, put a breakpoint at the very beginning of our programme, and examine if the pool contains these literals.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
...
public String repeat(int count) {
// ...
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
}
...
}
They are there indeed.
As an interesting find, this IDEA's filtering has a side effect: the substrings I was looking for have been added to the pool as well. The pool size increased by one ("bytes String" was added) after I applied this.contains("bytes String").
Where does this leave us?
We have no idea whether "First" was created and interned before we call String str1 = "First";, so we can't state firmly that the line creates a new instance.
With the given information, the question cannot be definitely answered. As is stated in the JLS, §15.18.1:
... To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
This means that the answer depends at least on the concrete Java compiler used.
I think the best we can do is give an interval as answer:
a smart compiler may be able to infer that str1 to str3 are never used and fold the concatenation during compilation, such that only one String-object is created (the one referenced by str4)
The maximum sensible number of Strings created should be 5: one each for str1 to str3, one for tmp = str1 + str2 and one for str4 = tmp + str3.
So... my answer would be "something between one to five String-objects". As to the total number of objects created just for this operation... I do not know. This may also depend how exactly e.g. StringBuffer is implemented.
As an aside: I wonder what the reason behind asking such questions is. Normally, one does not need to care about those details.
Java 8 will likely create 5 objects:
3 for the 3 literals
1 StringBuilder
1 for the concatenated String
With Java 9 things changed though and String concatenation does not use StringBuilder anymore.
It should be 5:
three for the three literals (assigned to str1, str2 and str3)
one for str1 + str2
one for (result from the previous operation) + str3 (assigned to str4)
A conformant Java implementation can concatenate the strings any number of ways, at run time or at compile time, needing any number of run-time objects, including zero objects if it detects that the result is not needed at run time.
4 string object will be created in string constant pool. 3 for literals and 1 with concatenation.
if we use
String s1 = new String("one")
it will create two object one in constant pool and one in heap memory.
if we define :
String s1 = "one";
String s2 = new String("one");
it will create two object one in constant pool and one in heap memory.
Concatenation operation doesn't create those many String objects. It creates aStringBuilder and then appends the strings. So there may be 5 objects,
3 (variables) + 1 (sb) + 1 (Concatenated string).

java String constants save heap memory? [duplicate]

What is String Interning in Java, when I should use it, and why?
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()
Basically doing String.intern() on a series of strings will ensure that all strings having same contents share same memory. So if you have list of names where 'john' appears 1000 times, by interning you ensure only one 'john' is actually allocated memory.
This can be useful to reduce memory requirements of your program. But be aware that the cache is maintained by JVM in permanent memory pool which is usually limited in size compared to heap so you should not use intern if you don't have too many duplicate values.
More on memory constraints of using intern()
On one hand, it is true that you can remove String duplicates by
internalizing them. The problem is that the internalized strings go to
the Permanent Generation, which is an area of the JVM that is reserved
for non-user objects, like Classes, Methods and other internal JVM
objects. The size of this area is limited, and is usually much smaller
than the heap. Calling intern() on a String has the effect of moving
it out from the heap into the permanent generation, and you risk
running out of PermGen space.
--
From: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html
From JDK 7 (I mean in HotSpot), something has changed.
In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
-- From Java SE 7 Features and Enhancements
Update: Interned strings are stored in main heap from Java 7 onwards. http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes
There are some "catchy interview" questions, such as why you get equals! if you execute the below piece of code.
String s1 = "testString";
String s2 = "testString";
if(s1 == s2) System.out.println("equals!");
If you want to compare Strings you should use equals(). The above will print equals because the testString is already interned for you by the compiler. You can intern the strings yourself using intern method as is shown in previous answers....
JLS
JLS 7 3.10.5 defines it and gives a practical example:
Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
Example 3.10.5-1. String Literals
The program consisting of the compilation unit (§7.3):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
JVMS
JVMS 7 5.1 says says that interning is implemented magically and efficiently with a dedicated CONSTANT_String_info struct (unlike most other objects which have more generic representations):
A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.
The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:
("a" + "b" + "c").intern() == "abc"
To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.
If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.
Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.
Bytecode
Let's decompile some OpenJDK 7 bytecode to see interning in action.
If we decompile:
public class StringPool {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a);
System.out.println(b);
System.out.println(a == c);
}
}
we have on the constant pool:
#2 = String #32 // abc
[...]
#32 = Utf8 abc
and main:
0: ldc #2 // String abc
2: astore_1
3: ldc #2 // String abc
5: astore_2
6: new #3 // class java/lang/String
9: dup
10: ldc #2 // String abc
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne 42
38: iconst_1
39: goto 43
42: iconst_0
43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
Note how:
0 and 3: the same ldc #2 constant is loaded (the literals)
12: a new string instance is created (with #2 as argument)
35: a and c are compared as regular objects with if_acmpne
The representation of constant strings is quite magic on the bytecode:
it has a dedicated CONSTANT_String_info structure, unlike regular objects (e.g. new String)
the struct points to a CONSTANT_Utf8_info Structure that contains the data. That is the only necessary data to represent the string.
and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by ldc.
I have done similar tests for fields, and:
static final String s = "abc" points to the constant table through the ConstantValue Attribute
non-final fields don't have that attribute, but can still be initialized with ldc
Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.
Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no CONSTANT_String_info analogue).
Update for Java 8 or plus.
In Java 8, PermGen (Permanent Generation) space is removed and replaced by Meta Space. The String pool memory is moved to the heap of JVM.
Compared with Java 7, the String pool size is increased in the heap. Therefore, you have more space for internalized Strings, but you have less memory for the whole application.
One more thing, you have already known that when comparing 2 (referrences of) objects in Java, '==' is used for comparing the reference of object, 'equals' is used for comparing the contents of object.
Let's check this code:
String value1 = "70";
String value2 = "70";
String value3 = new Integer(70).toString();
Result:
value1 == value2 ---> true
value1 == value3 ---> false
value1.equals(value3) ---> true
value1 == value3.intern() ---> true
That's why you should use 'equals' to compare 2 String objects. And that's is how intern() is useful.
Since strings are objects and since all objects in Java are always stored only in the heap space, all strings are stored in the heap space. However, Java keeps strings created without using the new keyword in a special area of the heap space, which is called "string pool". Java keeps the strings created using the new keyword in the regular heap space.
The purpose of the string pool is to maintain a set of unique strings. Any time you create a new string without using the new keyword, Java checks whether the same string already exists in the string pool. If it does, Java returns a reference to the same String object and if it does not, Java creates a new String object in the string pool and returns its reference. So, for example, if you use the string "hello" twice in your code as shown below, you will get a reference to the same string. We can actually test this theory out by comparing two different reference variables using the == operator as shown in the following code:
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); //prints true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str3); //prints false
System.out.println(str3 == str4); //prints false
== operator is simply checks whether two references point to the same object or not and returns true if they do. In the above code, str2 gets the reference to the same String object which was created earlier. However, str3 and str4 get references to two entirely different String objects. That is why str1 == str2 returns true but str1 == str3 and str3 == str4 return false .
In fact, when you do new String("hello"); two String objects are created instead of just one if this is the first time the string "hello" is used in the anywhere in program - one in the string pool because of the use of a quoted string, and one in the regular heap space because of the use of new keyword.
String pooling is Java's way of saving program memory by avoiding the creation of multiple String objects containing the same value. It is possible to get a string from the string pool for a string created using the new keyword by using String's intern method. It is called "interning" of string objects. For example,
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2.intern(); //get an interned string obj
System.out.println(str1 == str2); //prints false
System.out.println(str1 == str3); //prints true
OCP Java SE 11 Programmer, Deshmukh
String interning is an optimization technique by the compiler. If you have two identical string literals in one compilation unit then the code generated ensures that there is only one string object created for all the instance of that literal(characters enclosed in double quotes) within the assembly.
I am from C# background, so i can explain by giving a example from that:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
output of the following comparisons:
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
Note1:Objects are compared by reference.
Note2:typeof(int).Name is evaluated by reflection method so it does not gets evaluated at compile time. Here these comparisons are made at compile time.
Analysis of the Results:
1) true because they both contain same literal and so the code generated will have only one object referencing "Int32". See Note 1.
2) true because the content of both the value is checked which is same.
3) FALSE because str2 and obj does not have the same literal. See Note 2.
Java interning() method basically makes sure that if String object is present in SCP, If yes then it returns that object and if not then creates that objects in SCP and return its references
for eg: String s1=new String("abc");
String s2="abc";
String s3="abc";
s1==s2// false, because 1 object of s1 is stored in heap and other in scp(but this objects doesn't have explicit reference) and s2 in scp
s2==s3// true
now if we do intern on s1
s1=s1.intern()
//JVM checks if there is any string in the pool with value “abc” is present? Since there is a string object in the pool with value “abc”, its reference is returned.
Notice that we are calling s1 = s1.intern(), so the s1 is now referring to the string pool object having value “abc”.
At this point, all the three string objects are referring to the same object in the string pool. Hence s1==s2 is returning true now.
By using heap object reference, if we want to corresponding SCP object reference we should go for intern() method.
Example :
class InternDemo
{
public static void main(String[] args)
{
String s1=new String("smith");
String s2=s1.intern();
String s3="smith";
System.out.println(s2==s3);//true
}
}
intern flow chart

What is Java String interning?

What is String Interning in Java, when I should use it, and why?
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()
Basically doing String.intern() on a series of strings will ensure that all strings having same contents share same memory. So if you have list of names where 'john' appears 1000 times, by interning you ensure only one 'john' is actually allocated memory.
This can be useful to reduce memory requirements of your program. But be aware that the cache is maintained by JVM in permanent memory pool which is usually limited in size compared to heap so you should not use intern if you don't have too many duplicate values.
More on memory constraints of using intern()
On one hand, it is true that you can remove String duplicates by
internalizing them. The problem is that the internalized strings go to
the Permanent Generation, which is an area of the JVM that is reserved
for non-user objects, like Classes, Methods and other internal JVM
objects. The size of this area is limited, and is usually much smaller
than the heap. Calling intern() on a String has the effect of moving
it out from the heap into the permanent generation, and you risk
running out of PermGen space.
--
From: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html
From JDK 7 (I mean in HotSpot), something has changed.
In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
-- From Java SE 7 Features and Enhancements
Update: Interned strings are stored in main heap from Java 7 onwards. http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes
There are some "catchy interview" questions, such as why you get equals! if you execute the below piece of code.
String s1 = "testString";
String s2 = "testString";
if(s1 == s2) System.out.println("equals!");
If you want to compare Strings you should use equals(). The above will print equals because the testString is already interned for you by the compiler. You can intern the strings yourself using intern method as is shown in previous answers....
JLS
JLS 7 3.10.5 defines it and gives a practical example:
Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
Example 3.10.5-1. String Literals
The program consisting of the compilation unit (§7.3):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
JVMS
JVMS 7 5.1 says says that interning is implemented magically and efficiently with a dedicated CONSTANT_String_info struct (unlike most other objects which have more generic representations):
A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.
The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:
("a" + "b" + "c").intern() == "abc"
To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.
If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.
Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.
Bytecode
Let's decompile some OpenJDK 7 bytecode to see interning in action.
If we decompile:
public class StringPool {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a);
System.out.println(b);
System.out.println(a == c);
}
}
we have on the constant pool:
#2 = String #32 // abc
[...]
#32 = Utf8 abc
and main:
0: ldc #2 // String abc
2: astore_1
3: ldc #2 // String abc
5: astore_2
6: new #3 // class java/lang/String
9: dup
10: ldc #2 // String abc
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne 42
38: iconst_1
39: goto 43
42: iconst_0
43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
Note how:
0 and 3: the same ldc #2 constant is loaded (the literals)
12: a new string instance is created (with #2 as argument)
35: a and c are compared as regular objects with if_acmpne
The representation of constant strings is quite magic on the bytecode:
it has a dedicated CONSTANT_String_info structure, unlike regular objects (e.g. new String)
the struct points to a CONSTANT_Utf8_info Structure that contains the data. That is the only necessary data to represent the string.
and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by ldc.
I have done similar tests for fields, and:
static final String s = "abc" points to the constant table through the ConstantValue Attribute
non-final fields don't have that attribute, but can still be initialized with ldc
Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.
Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no CONSTANT_String_info analogue).
Update for Java 8 or plus.
In Java 8, PermGen (Permanent Generation) space is removed and replaced by Meta Space. The String pool memory is moved to the heap of JVM.
Compared with Java 7, the String pool size is increased in the heap. Therefore, you have more space for internalized Strings, but you have less memory for the whole application.
One more thing, you have already known that when comparing 2 (referrences of) objects in Java, '==' is used for comparing the reference of object, 'equals' is used for comparing the contents of object.
Let's check this code:
String value1 = "70";
String value2 = "70";
String value3 = new Integer(70).toString();
Result:
value1 == value2 ---> true
value1 == value3 ---> false
value1.equals(value3) ---> true
value1 == value3.intern() ---> true
That's why you should use 'equals' to compare 2 String objects. And that's is how intern() is useful.
Since strings are objects and since all objects in Java are always stored only in the heap space, all strings are stored in the heap space. However, Java keeps strings created without using the new keyword in a special area of the heap space, which is called "string pool". Java keeps the strings created using the new keyword in the regular heap space.
The purpose of the string pool is to maintain a set of unique strings. Any time you create a new string without using the new keyword, Java checks whether the same string already exists in the string pool. If it does, Java returns a reference to the same String object and if it does not, Java creates a new String object in the string pool and returns its reference. So, for example, if you use the string "hello" twice in your code as shown below, you will get a reference to the same string. We can actually test this theory out by comparing two different reference variables using the == operator as shown in the following code:
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); //prints true
String str3 = new String("hello");
String str4 = new String("hello");
System.out.println(str1 == str3); //prints false
System.out.println(str3 == str4); //prints false
== operator is simply checks whether two references point to the same object or not and returns true if they do. In the above code, str2 gets the reference to the same String object which was created earlier. However, str3 and str4 get references to two entirely different String objects. That is why str1 == str2 returns true but str1 == str3 and str3 == str4 return false .
In fact, when you do new String("hello"); two String objects are created instead of just one if this is the first time the string "hello" is used in the anywhere in program - one in the string pool because of the use of a quoted string, and one in the regular heap space because of the use of new keyword.
String pooling is Java's way of saving program memory by avoiding the creation of multiple String objects containing the same value. It is possible to get a string from the string pool for a string created using the new keyword by using String's intern method. It is called "interning" of string objects. For example,
String str1 = "hello";
String str2 = new String("hello");
String str3 = str2.intern(); //get an interned string obj
System.out.println(str1 == str2); //prints false
System.out.println(str1 == str3); //prints true
OCP Java SE 11 Programmer, Deshmukh
String interning is an optimization technique by the compiler. If you have two identical string literals in one compilation unit then the code generated ensures that there is only one string object created for all the instance of that literal(characters enclosed in double quotes) within the assembly.
I am from C# background, so i can explain by giving a example from that:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
output of the following comparisons:
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
Note1:Objects are compared by reference.
Note2:typeof(int).Name is evaluated by reflection method so it does not gets evaluated at compile time. Here these comparisons are made at compile time.
Analysis of the Results:
1) true because they both contain same literal and so the code generated will have only one object referencing "Int32". See Note 1.
2) true because the content of both the value is checked which is same.
3) FALSE because str2 and obj does not have the same literal. See Note 2.
Java interning() method basically makes sure that if String object is present in SCP, If yes then it returns that object and if not then creates that objects in SCP and return its references
for eg: String s1=new String("abc");
String s2="abc";
String s3="abc";
s1==s2// false, because 1 object of s1 is stored in heap and other in scp(but this objects doesn't have explicit reference) and s2 in scp
s2==s3// true
now if we do intern on s1
s1=s1.intern()
//JVM checks if there is any string in the pool with value “abc” is present? Since there is a string object in the pool with value “abc”, its reference is returned.
Notice that we are calling s1 = s1.intern(), so the s1 is now referring to the string pool object having value “abc”.
At this point, all the three string objects are referring to the same object in the string pool. Hence s1==s2 is returning true now.
By using heap object reference, if we want to corresponding SCP object reference we should go for intern() method.
Example :
class InternDemo
{
public static void main(String[] args)
{
String s1=new String("smith");
String s2=s1.intern();
String s3="smith";
System.out.println(s2==s3);//true
}
}
intern flow chart

Categories