String pool Objects [duplicate] - java

This question already has answers here:
Questions about Java's String pool [duplicate]
(7 answers)
Closed 7 years ago.
Can you please clarify me, how many objects will be created in below case and why? I am slightly confused with this.
String s1 = "cat";
String s2 = "cat";
String s3 = "c"+"at";
String s4 = new String("cat");
String s5 = "kitty"+"cat";
String s6 = new String("kittycat");
String s7 = s5;
String s8= new String(s5); // Newly Added in this Question

Let's look step-by-step:
String s1 = "cat";
String s2 = "cat";
These two will be just the same constant pool entry created in your class file by javac compiler. When this class is loaded, this string (along with all other constant pool strings) will be automatically interned, thus it will be also merged with other "cat" strings in other classes.
String s3 = "c"+"at";
This is practically the same: if string concatenation can be computed during the compilation, it's done by javac. So it's practically the same as s1 and s2. This is covered by JLS, chapter 15.18.1:
The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).
String s4 = new String("cat");
Here you explicitly create a new object. Java language guarantees that when you use a new keyword, you will have a new distinct object which cannot be the same as any of objects created previously. However if you use this object only in current methods (or in methods which can be inlined into the current) and don't use == operation to compare it with other strings, JIT compiler can skip the object allocation for optimization. But if you actually use == or System.identityHashCode, or this method is executed as interpreted frame, then it will be actually new object.
The "cat" string which is passed to the parameter is actually the same object as s1, s2, and s3.
String s5 = "kitty"+"cat";
This is similar to s3: the javac compiler will just create a "kittycat" string during the compilation. Looking into bytecode you cannot even know that there was a concatenation in the source.
String s6 = new String("kittycat");
This is similar to s4: new object is created explicitly. If you try to use s6 == "kittycat" later, you will get false.
String s7 = s5;
Here you just assign a reference to the previously created s5 string, thus no new object is created here.
So the answer is: at most 4 strings will be created, but in some cases it can be optimized down to 2 strings. And the most important: if you try to check how many strings you have from inside the same program (i.e. not using Java agent or analysing memory dump), you will always get four.

user3360241 - Your answer seems to be correct... Not sure why it's been down voted without giving any explanation... if you do this the size will be two..
Set<Integer> set = new HashSet<Integer>();
set.add(s1.hashCode());
set.add(s2.hashCode());
set.add(s3.hashCode());
set.add(s4.hashCode());
set.add(s5.hashCode());
set.add(s6.hashCode());
set.add(s7.hashCode());
System.out.println("size :: "+set.size());

Related

Java String Memory-Address [duplicate]

This question already has an answer here:
How is String concatenation working in following
(1 answer)
Closed 1 year ago.
Why is the result false?
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1+s2;
System.out.println(s3==s4);
As I know, there's already one "helloworld" in the constant pool.
Thanks for answering, but what I want to ask is not the difference between "==" and "equals", I just want to make sure s1+s2; makes a new String, even though there's already one String Object with value "helloworld" in memory.
You need to understand that they all are object instance of class String
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
This creates 3 objects with different values and different memory
String s4 = s1+s2;
Now you are again creating a new object with same value as s1 and s2 but since its a new object it has different memory.
System.out.println(s3==s4);
Now with this line you are trying to compare the values for these 2 objects and in String class the correct way to do it is by using equals() method i.e.,
System.out.println(s3.equals(s4));
For detailed information please check this:
https://www.geeksforgeeks.org/difference-equals-method-java/
(s3==s4) - means comparing references, not values. reference s3 is not the same as reference s4. s3 and s4 are two different instances of String.
use equals for comparing values of objects. override equals for your own classes if it necessary.

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.

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

Java:literal strings

class A {
String s4 = "abc";
static public void main(String[]args ) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
A o = new A();
String s5 = new String("def");
System.out.println("s1==s2 : " + (s1==s2));
System.out.println("s1==s1.intern : " + (s1==s1.intern()));
System.out.println("s1==s3 : " + (s1==s3));
System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern()));
System.out.println("s1==s4 : " + (s1==o.s4));
}
}
The output:
s1==s2 : true
s1==s1.intern : true
s1==s3 : false
s1.intern==s3.intern : true
s1==s4 : true
My questions:
1.What happens for "String s1 = "abc"? I guess the String object is added to the pool in class String as an interned string? Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?
2.What happens for "String s2 = "abc"? I guess no any object is created.But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?
3.Seems String s3 = new String("abc") does not use interned string.Why?
4.Will String s5 = new String("def") create any new interned string?
The compiler creates a String object for "abc" in the constant pool, and generates a reference to it in the bytecode for the assignment statement.
See (1). No searching; no performance issue.
This creates a new String object at runtime, because that is what the 'new' operator does: create new objects.
Yes, for "def", but because of (3) a new String is also created at runtime.
The String objects at 3-4 are not interned.
1.What happens for "String s1 = "abc"?
At compile time a representation of the literal is written to the "constant pool" part of the classfile for the class that contains this code.
When the class is loaded, the representation of the string literal in the classfile's constant pool is read, and a new String object is created from it. This string is then interned, and the reference to the interned string is then "embedded" in the code.
At runtime, the reference to the previously created / interned String is assigned to s1. (No string creation or interning happens when this statement is executed.)
I guess the String object is added to the pool in class String as an interned string?
Yes. But not when the code is executed.
Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?
It is stored in the permgen region of the heap. (The String class has no static fields. The JVM's string pool is implemented in native code.)
2.What happens for "String s2 = "abc"?
Nothing happens at load time. When the compiler created the classfile, it reused the same constant pool entry for the literal that was used for the first use of the literal. So the String reference uses by this statement is the same one as is used by the previous statement.
I guess no any object is created.
Correct.
But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?
No, and No. The Java interpretter (or JIT compiled code) uses the same reference as was created / embedded for the previous statement.
3.Seems String s3 = new String("abc") does not use interned string.Why?
It is more complicated than that. The constructor call uses the interned string, and then creates a new String, and copies the characters of the interned string to the new String's representation. The newly created string is assigned to s3.
Why? Because new is specified as always creating a new object (see JLS), and the String constructor is specified as copying the characters.
4.Will String s5 = new String("def") create any new interned string?
A new interned string is created at load time (for "def"), and then a new String object is created at runtime which is a copy of the interned string. (See previous text for more details.)
See this answer on SO. Also see this wikipedia article on String Interning.
String s1 = "abc"; creates a new String and interns it.
String s2 = "abc"; will drag the same Object used for s1 from the intern pool. The JVM does this to increase performance. It is quicker than creating a new String.
Calling new String() is redundant as it will return a new implicit String Object. Not retrieve it from the intern pool.
As Keyser says, == compares the Strings for Object equality, returning true if they are the same Object. When comparing String content you should use .equals()

Strings are objects in Java, so why don't we use 'new' to create them?

We normally create objects using the new keyword, like:
Object obj = new Object();
Strings are objects, yet we do not use new to create them:
String str = "Hello World";
Why is this? Can I make a String with new?
In addition to what was already said, String literals [ie, Strings like "abcd" but not like new String("abcd")] in Java are interned - this means that every time you refer to "abcd", you get a reference to a single String instance, rather than a new one each time. So you will have:
String a = "abcd";
String b = "abcd";
a == b; //True
but if you had
String a = new String("abcd");
String b = new String("abcd");
then it's possible to have
a == b; // False
(and in case anyone needs reminding, always use .equals() to compare Strings; == tests for physical equality).
Interning String literals is good because they are often used more than once. For example, consider the (contrived) code:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
If we didn't have interning of Strings, "Next iteration" would need to be instantiated 10 times, whereas now it will only be instantiated once.
Strings are "special" objects in Java. The Java designers wisely decided that Strings are used so often that they needed their own syntax as well as a caching strategy. When you declare a string by saying:
String myString = "something";
myString is a reference to String object with a value of "something". If you later declare:
String myOtherString = "something";
Java is smart enough to work out that myString and myOtherString are the same and will store them in a global String table as the same object. It relies on the fact that you can't modify Strings to do this. This lowers the amount of memory required and can make comparisons faster.
If, instead, you write
String myOtherString = new String("something");
Java will create a brand new object for you, distinct from the myString object.
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
Hope this clears a few doubts. :)
We usually use String literals to avoid creating unnecessary objects. If we use new operator to create String object , then it will create new object everytime .
Example:
String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);
For the above code in memory :
It's a shortcut. It wasn't originally like that, but Java changed it.
This FAQ talks about it briefly. The Java Specification guide talks about it also. But I can't find it online.
String is subject to a couple of optimisations (for want of a better phrase). Note that String also has operator overloading (for the + operator) - unlike other objects. So it's very much a special case.
In Java, Strings are a special case, with many rules that apply only to Strings. The double quotes causes the compiler to create a String object. Since String objects are immutable, this allows the compiler to intern multiple strings, and build a larger string pool. Two identical String constants will always have the same object reference. If you don't want this to be the case, then you can use new String(""), and that will create a String object at runtime. The intern() method used to be common, to cause dynamically created strings to be checked against the string lookup table. Once a string in interned, the object reference will point to the canonical String instance.
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
When the classloader loads a class, all String constants are added to the String pool.
Well the StringPool is implemented using The Hashmap in java. If we are creating always with a new keyword its not searching in String Pool and creating a new memory for it which might be needed later if we have a memory intensive operation running and if we are creating all the strings with new keyword that would affect performance of our application. So its advisable to not to use new keywords for creating string because then only it will go to String pool which in turn is a Hashmap ,(memory saved , imagine if we have lots of strings created with new keyword ) here it will be stored and if the string already exists the reference of it(which would usually reside in Stack memory) would be returned to the newly created string.
So its done to improve performance .
Syntactic sugar. The
String s = new String("ABC");
syntax is still available.
You can still use new String("string"), but it would be harder to create new strings without string literals ... you would have to use character arrays or bytes :-) String literals have one additional property: all same string literals from any class point to same string instance (they are interned).
There's almost no need to new a string as the literal (the characters in quotes) is already a String object created when the host class is loaded. It is perfectly legal to invoke methods on a literal and don, the main distinction is the convenience provided by literals. It would be a major pain and waste of tine if we had to create an array of chars and fill it char by char and them doing a new String(char array).
Feel free to create a new String with
String s = new String("I'm a new String");
The usual notation s = "new String"; is more or less a convenient shortcut - which should be used for performance reasons except for those pretty rare cases, where you really need Strings that qualify for the equation
(string1.equals(string2)) && !(string1 == string2)
EDIT
In response to the comment: this was not intended to be an advise but just an only a direct response to the questioners thesis, that we do not use the 'new' keyword for Strings, which simply isn't true. Hope this edit (including the above) clarifies this a bit. BTW - there's a couple of good and much better answers to the above question on SO.
The literal pool contains any Strings that were created without using the keyword new.
There is a difference : String without new reference is stored in String literal pool and String with new says that they are in heap memory.
String with new are elsewhere in memory just like any other object.
Because String is an immutable class in java.
Now why it is immutable?
As String is immutable so it can be shared between multiple threads and we dont need to synchronize String operation externally.
As String is also used in class loading mechanism. So if String was mutable then java.io.writer could have been changed to abc.xyz.mywriter
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
Output:
True
I created two separate objects, both have a field(ref) 'Name'. So even in this case "Jan Peter" is shared, if I understand the way java deals..

Categories