Each time you create a string literal, the JVM checks the "string constant pool" first. If the string already exists in the pool, a reference to the pooled instance is returned. If the string doesn't exist in the pool, a new string instance is created and placed in the pool.
In other words, we don't create any String object using new keyword above. The JVM does that task for us, it create a String object. If the String object exist in the memory, it doesn't create a new String object rather it assigns the same old object to the new instance, that means even though we have two String instances above(str1 and str2) compiler only created one String object and assigned the same to both the instances.
For example there are 5 String instances that have same value, it means that in memory there is only one String object having the value and all the 5 String instances would be pointing to the same String object.
What if we want to have two different String object with the same String. For that we would need to create Strings using new keyword
2- Using new keyword
String str1 = new String("Hello World!");
String str2 = new String("Hello World!");
In such case, the JVM will create a new String object in normal (non-pool) heap memory.
Notice that JVM handles allocation of memory space for string variables efficiently, whenever we create a String variable and assign a String value with String Literal(double quotes) , JVM check value of String variable in String pool, if found, it returns reference of String object, if not found then it creates a new String object in String pool and return reference of it.
I found some images from google to represent. So, there are three images below.
# add these three lines at the end of file and CTRL+X and Y and click enter :)