Can string pool contain two strings with the same value? [duplicate] - java

This question already has answers here:
Questions about Java's String pool [duplicate]
(7 answers)
Closed 9 years ago.
Can string pool contain two strings with the same value??
String str = "abc";
String str1 = new String("abc");
Will the second statement with `new()` operator creates two objects of `string` "abc", one on `heap` and another on `string` pool?
Now if i call intern() on str1 ie str1.intern(); as a third statement, will str1 refer to the "abc" from String pool?
If yes then what will happen to the object that was created on heap earlier by the new(). Will that object be eligible for garbage collection.?
If no then what will be the result of str1.intern();?

No first will also create one object and also second one will create only one string object. Difference is that first one will create in String pool and second one will create in heap only.
If you will call str1.intern(); then it will be added to String pool.
String str1 = "abc";
String str2 = new String("abc");
Stirng str3 = "abc"
Here two objects will be created. first line will create one strong object with reference str1 and 3rd line will point to the same object created in 1st line with reference str3 but in 2nd line one new object will be created as we are using new keyword here. Hope it will help you.
Also check this answer. Good explanation is there.

"abc" object will be created on class loading and put on String pool. The second line will use String(String original) constructor where original is the pointer to "abc" in pool. This is the bytecode for the second line:
NEW java/lang/String
DUP
LDC "abc"
INVOKESPECIAL java/lang/String.<init>(Ljava/lang/String;)V
ASTORE 2

new String("abc") is a class instance creation expression, and must create a new object. Whether it shares the same char array internally as the literal "abc" is up to the String implementation. Both the "abc" references will use the same intern String.

String t1 = "ABC";
String t2 = new String("ABC");
String t3 = "ABC";
System.out.println(t1 == t2);
System.out.println(t2 == t3);
System.out.println(t1 == t3);
generates the following output (Java SE 7):
false
false
true

It is basically :
// "abc" is interned by the JVM in the pool
String str="abc";
// JVM uses the pooled "abc" to create a new instance
String str1=new String("abc");
Only one new String object is created referenced by str1 . The String literal "abc" was interned by the JVM. Since the literal "abc" already existed in the String pool , in the second statement , JVM should use that .

Related

Java Strings Confusion [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");
if (s1 == s2) is giving true
while (s3 == s4) is giving false.
Can somebody give a detailed explanation onto what is String pool, heap, how many objects are created in each line and how many objects created in total.
Why s3==s4 is giving false?
A detailed explanation will be much appreciated.
When you do new String(...), it is evaluated at runtime and hence creates two different instances and you end up getting s3 == s4 as false. Same thing happens when you use StringBuilder and do something like sb.toString() which is again evaluated at runtime.
For Example,
StringBuilder sb = new StringBuilder();
String foo = sb.append("abc").toString();
String bar = new String("abc");
String foobar = "abc";
Here foo, bar and foobar are all different objects and hence foo == bar or foo == foobar will evaluate to false.
On the other hand s1 == s2 returns true because abc one declared, already exists in the String Pool and in this case both the objects points to the same reference in the pool.
String Class in java is defined in java.lang package and it is exactly that, a class and not a primitive like int or boolean.
Strings are developed to offer operations with many characters ans are commmonly used in almost all the Java applications
Some interesting facts about Java and Strings:
String in immutable and final in Java and in this case JVM uses String Pool to store all the String objects.
What are different ways to create String Object?
We can create String object using new operator like any normal java class or we can use double quotes (literal assignment) to create a String object.
There are too several constructors available in String class to get String from char array, byte array, StringBuffer and StringBuilderetc etc.
To your Question:
When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
When we use new operator, JVM creates the String object but don’t store it into the String Pool. We can use intern() method to store the String object into String pool or return the reference if there is already a String with equal value present in the pool.
So when you do
String s1 = "abc";
String s2 = "abc";
those are checked in the StringPool and since s1 already exist there, s2 will take the same reference, hence, s1 ==s2 is true.
but when you do:
String s3 = new String("abc");
String s4 = new String("abc");
you are using the new operator, therefore the JVM is not checking if there is an string already in the heap, it will just allocate a new space for s4, so is s3==s4 ??? of course no.
Please take a look at the image below for a more illustrative example.

Count Distinct String Object Instances

How many distinct String object instances are created in the following code segment?
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
Not sure about all my reasoning here.
By using the keyword new that creates an instance from the String class, I am guessing that has to be an object. However, I am confused, is String after the new now considered a method because it has ( ) and then it is calling a String literal "hello" in it?
String s2 = "Goodbye";
I think this is a String literal, and since Strings are actually objects even the String literal is considered object. Not 100% sure if that is true.
String s3 = s1; Just refers back to s1. Therefore, it is not distinct.
So my answer is 2 distinct objects.
Please explain if I am a right or wrong.
The correct answer is 3.
String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;
The compiler will put both literals "hello" and "GoodBye" into a "constant pool" during compilation time, which then will be loaded by the classloader. So the JVM automatically interns all String literals used by this class, when it loads that class. More about this: When are Java Strings interned?. The String constant pool is then managed during runtime.
During runtime the JVM will create the third String object when it reaches the line String s1 = new String("hello").
So you would and up with three distinct String objects, where two of them contain the same word "hello". So s1.equals("hello") would be true, but s1 == "hello" would be false, because s1 references to a different String on the heap, than the literal "hello".
The line String s3 = s1 just creates a variable s3 with a copied reference to the String object of s1. It doesn't create a new object.
Also mind that you can "manually" add Strings into the String constant pool by using the method String#intern. So s1.intern() == "hello" is true, because the String reference returned from s1.intern() is the reference to the literal "hello" which was already in the constant pool.
If you like to get another and maybe more detailed explanation with some drawings about objects and their location, you can check this article on javaranch.

Confusion about new String and String literals in Java

According to Kathy Sierra's book:
String s = "abc"; // creates one String object and one
// reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects,
// and one reference variable
In this case, because we used the new keyword, Java will create a new String object in normal (nonpool) memory, and s will refer to it. In addition,the literal "abc" will be placed in the pool.
As I know, when we use literals, it stores value in pool but when we use new keyword it creates object in heap. Here I want to know, is the heap object refer pool data (String) or not?
The variable you created using new String("abc") is not the same as the pool "abc" string.
String string1 = "abc";
String string2 = new String("abc");
System.out.println(string1.equals(string2)); //will print true
System.out.println(string1 == string2); //will print false

How to find the no. of String objects created in the java heap and in the String literal pool

Basically I need to find the no. of String objects created by my piece of code, in java heap and String pool.I don't need the entire String object count in the JVM. I only need the object count created by my code.
Suppose:
String string1 = "a";
String string2 = new String("a");
Then the count of objects will be 2 in the heap and 1 entry in the string pool.(Correct me if I am wrong)
String pool may or may not be stored on the heap so you can't really oppose the two.
String s1 = "a"
=> the string literal "a" will be in the string pool, and s1 is a reference to that string instance
String s2 = new String("a")
=> the string literal "a" is already in the pool, so no new string created there
=> new String(...) a new string is created which is not in the pool and s2 is a reference to that instance
So in total: "a" in the pool and new String("a") not in the pool => 2 string instances in total.
For String s1 ="a", it will create an object in String Constant pool with the reference s1 pointing to that object.
For String s2 = new String("a"), it will create an object in Heap area with the reference s2 pointing to that object. Then in String Constant pool already "a" has an object so it directly pointing to that.(ie)In String Constant pool duplicates objects are not allowed. So in this case 2 Object will be created.

Strings [= new String vs = ""]

So my question is in relation to declaring and assigning strings.
The way I usually declare strings is by doing the following:
String s1 = "Stackoverflow";
And then if I ever need to change the value of s1 I would do the following:
s1 = "new value";
Today I found another way of doing it and declaring a string would go like:
String s2 = new String("Stackoverflow");
And then changing the value would be:
s2 = new String("new value");
My question is what is the difference between the two or is it simply preferential. From looking at the code the fourth line
s2 = new String ("new value");
I'm assuming that doing that would create a new memory location and s2 would then point to it so I doubt it would be used to change the value but I can see it being used when declaring a string.
From the javadoc :
Initializes a newly created String object so that it represents the
same sequence of characters as the argument; in other words, the newly
created string is a copy of the argument string. Unless an explicit
copy of original is needed, use of this constructor is unnecessary
since Strings are immutable.
So no, you have no reason not to use the simple literal.
Simply do
String s1 = "Stackoverflow";
Historically, this constructor was mainly used to get a lighter copy of a string obtained by splitting a bigger one (see this question). Now, There's no normal reason to use it.
String s1 = "Stackoverflow"; // declaring & initializing s1
String s2 = new String("Stackoverflow"); // declaring & initializing s2
in above cases you are declaring & initializing String object.
The difference between
//first case
String s2 = new String("new String"); // declaring & initializing s2 with new memory
// second case
s2 = "new String" // overwriting previous value of s2
is in the first case you are creating a new object, i-e; allocating memory for a new object which will be refrenced by s2. The previous address to which s2 was pointing/referencing hasn't released the memory yet which will be gc when the program ends or when system needs to.
The good programming practice (second case) is to initialize an object once, and if you want to change its value either assign null to it and then allocate new memory to it or in case of string you can do like this
s2= "new String";
String s1 = "Stackoverflow";
This line will create a new object in the String pool if it does not exist already. That means first it will first try searching for "Stackoverflow" in the String pool, if found then s1 will start pointing to it, if not found then it will create a new object and s1 will refer to it.
String s2 = new String("Stackoverflow");
Will always create a new String object, no matter if the value already exists in the String pool. So the object in the heap would then have the value "Stackovrflow" and s2 will start pointing to it.
s2 = new String("new value");
This will again create a new Object and s2 will start pointing to it. The earlier object that s2 was pointing to is not open for garbage collection (gc).
Let me know if this helps.
The main difference is that the constructor always creates a totally new instance of String containing the same characters than the original String.
String s1 = "Stackoverflow";
String s2 = "Stackoverflow";
Then s1 == s2 will return true
String s1 = "Stackoverflow";
String s2 = new String("Stackoverflow");
Then s1 == s2 will return false
Just using the double quotes option is often better:
With a constructors you might create two instance of String.
Easier to read and less confusing
#user2612619 here i want to say is .. when ever ur creating object with "new" operator it always falls in heap memory . so wenever u have same content but different objects than also it will create new objects on heap by this u cant save memory ....
but in order to save memory java people brought concept of immutable where we can save memory .. if u r creating a different object with same content .. string will recognize dat difference and creates only one object with same content and points the two references to only one object ..
i can solve ur doubts from this figure ..
case 1:
String s = new String("stackoverflow");
String s1 = new String("stackoverflow");
as they are two different objects on heap memory with two different values of hashcode .. so s==s1 (is reference comparison) it is false .. but s.equals(s1) is content comparison ..so it is true
case 2:
String s = "stackoverflow";
String s1 = "stackoverflow";
here objects fall in scp(string constant pool memory)
same object for two different refernces .. so hashcode also same .. same reference value .. so s==s1 is true here [u can observe from figure clearly]
s.equals(s1) is true as content comparison.. this is very beautiful concept .. u will love it wen u solve some problems ... all d best
Creating String object Directly:
String s1 = "Hip Hop"
will create a string object but first JVM checks the String constant or literal pool and if the string does not exist, it creates a new String object “Hip jop” and a reference is maintained in the pool. The variable s1 also refers the same object. Now, if we put a statement after this:
String s2 = "Hip Hop"
JVM checks the String constant pool first and since the string already exists, a reference to the pooled instance is returned to s2.
System.out.println(s1==s2) // comparing reference and it will print true
java can make this optimization since strings are immutable and can be shared without fear of data corruption.
Creating String Object using new
String s3 = new String("Hip Hop")
For new keyword, a String object is created in the heap memory wither or not an equal string object already exists in the pool and s3 will refer to the newly created one.
System.out.println(s3==s2) // two reference is different, will print false
String objects created with the new operator do not refer to objects in the string pool but can be made to using String’s intern() method. The java.lang.String.intern() returns an interned String, that is, one that has an entry in the global String literal pool. If the String is not already in the global String literal pool, then it will be added to the pool.
String s4 = s3.intern();
Systen.out.println(s4 == s2); // will print `true` because s4 is interned,
//it now have the same reference to "Hip Hop" as s2 or s1
But try:
Systen.out.println(s4 == s3) // it will be false,
As the reference of s4, s2 and s1 is the reference to the pooled instance while s3 is referring to the created object in heap memory.
use of new for creting string:
prior to OpenJDK 7, Update 6, Java String.susbtring method had potential memory leak. substring method would build a new String object keeping a reference to the whole char array, to avoid copying it. You could thus inadvertently keep a reference to a very big character array with just a one character string. If we want to have minimal strings after substring, we use the constructor taking another string :
String s2 = new String(s1.substring(0,1));
The issue is resolved in JDK 7 update 6. So No need to create string with new any more for taking advantage provided by String literal pool mechanism.
Referance:
String literal pool
using new to prevent memory leak for using substring

Categories