java String's immutability - java

If I run,
String s1="abc";
then are there any differences between:
String s2=new String(s1);
and
String s2="abc";
Here's what I'm confused about:
The Head First Java says:"If there's already a String in the String pool with the same value, the JVM doesn't create a duplicate, it simply refers your reference variable to the existing entry. " Which at my point of view is that the s1 has already created "abc",s2 just refers to it. Am I right??

When you write String s2="abc"; and "abc" is already in the pool, then you won't get a duplicate - you'll get a reference to the existing String.
But if you write new String(something), you get a new String, whether there's a matching String in the pool or not.

String Constant Pool comes into picture in this case as shown in below screenshot.
I think it will help you to understand it visually.
String s1="abc"; // s1 will go to String constant pool
String s2=new String(s1); // any object created by "new" keyword will go to Heap
String s2="abc"; // s1 and s2 both will refer to same string in constant pool

the new keyword will force to create a new string object in heap even it already exist in string pool

Related

What is happening when you "alter" a string in Java using "+="?

I understand that a String variable in Java is immutable and can therefore not be changed.
String myString = "Hello.";
myString += " ";
myString += "My name is Kevin";
Each time we "add" something to this String(), we are effectively creating a new String(), but this has the same name as the string it is being concatenated with. Does this mean there are multiple references in memory with the variable "myString"?
Each time you "modify"/concatenate the String with +=, you're creating a new String object and replacing the reference named myString with the newly-created String. So no, there is only one reference in memory, but the object the reference points to changes each time. The string is immutable, so the object cannot be modified "in place".
String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. All information in an instance is initialized when the instance is created and the information can not be modified. There are many advantages of immutable classes.
There is a great answer on the Programmer's StackExchange explaining why Strings are immutable in Java, and more details about how exactly this works.
The best way to do this is to just use the StringBuilder() class:
String myStringBuilder = new StringBuilder("Hello.");
myStringBuilder.append(" ");
myStringBuilder.append("My name is Kevin");
System.out.println(myStringBuilder.toString());
However, String concatenation is translated into StringBuilder operations automatically by modern Java compilers.
No , you can not access to previous reference and it's left for garbage collector to collect it. in other words there is only one reference in memory which holds the current value of variable("My Name is Kevin)
note that if you r gonna change a String variable a lot , you should use StringBuilder class.
here is link to Documentation of StringBuilder class
you also can find lots example for using this class on internet
https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html
also here is detailed answer of your question
When will a string be garbage collected in java
String myString = "Hello.";
The above create a new Object and put "Hello." into memory which myString is reference to the Object.
myString += " ";
Here you can look as myString = myString + " "; a " " String is created and put into memory and the concatenation will result to create a new String which is referenced by myString.
Note that String concatenation with "+" has a O(N2) complexity while StringBuilder has O(N) in complexity. It is becase new String is created for the concatenation result every time while StringBuilder instead contains a sequence of characters. Therefore String concatenation is less efficient than using a StringBuilder especially need to build up a large amount of String.
Java uses a string pool. This is an implementation of the concept of string interning.
In computer science, string interning is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.
This means that for every string, a copy of that particular string is added to the string pool. Every variable that holds that exact string, points to that copy in the string pool.
The strings Hello., , and My name is Kevin are added to the string pool, since they're literals in the program.
String myString = "Hello.";
The variable myString starts pointing to the string Hello., which is already in the string pool.
myString += " ";
The string Hello. (note the extra space at the end) is added to the pool. The variable myString now points to that.
myString += "My name is Kevin";
The string Hello. My name is Kevin is added to the pool. The variable myString now points to that.
Strings in the pool that are no longer being referenced by variables, are eligible for garbage collection, so Hello. (with the space at the end), can now be garbage collected.
here your Code in which you define a String reference variable myString.
String is a immutable class, it means there is no modification can be made in object once it created.
Here "Hello" creates a String Object and refer the object by myString.
String myString = "Hello."; //create a Object String contain Hello and refer to myString
myString += " ";
myString += "My name is Kevin";
when myString+=" "; getting executed it creates another new object of String by concaticate "Hello" in it.
"Hello " a new Object created and myString refers to it. "Hello" is eligible for garbage Collection.
again when myString += "My name is Kevin"; getting executed, it creates another new Object of String by concatinate "Hello " in it.
Your new Object "Hello My Name is Kevin" is referred by myString reference Variable of String Type.
Now, Your both earlier Objects "Hello" and "Hello/s" is not referenced by any other reference variable, So, It is eligible for garbage Collection.
Thanks

String s = new String("abc") memory allocation [duplicate]

This question already has answers here:
What is the Java string pool and how is "s" different from new String("s")? [duplicate]
(5 answers)
Closed 7 years ago.
String s = new String("abc")
I know that this would create a new String object in Heap.
But i am confused about a statement in SCJP book by Kathy Sierra.
It states that the above statement would create an object in heap and at the same if the String "abc" is not present in the String pool , it would also add "abc" to the String pool.
Could anyone please tell me if the object "abc" is also created in the String pool in the above case.
String s = new String("abc")
Yes,above line will create two objects, one in string pool and other in Heap.
So, now
1) If you create a string literal like:-
String s1="abc"; //abc value will be taken from string pool which is previously added
2) If you create a String object and call intern method, no new object will be created instead it will just refer to "abc" present in string pool.
String s2=new String("abc").intern();
Note: When we are creating new String object based on existing one, it reuses char[] value.
Since new String(someStringValue) creates an exact copy of existing string and strings are immutable, there is clearly no reason for the two to exist at the same time.
Even if you have two String objects, they might still point to the same content.
You can refer this:- https://dzone.com/articles/string-memory-internals
Yes, it will be created as you are not having the same string before this line in your code. Now consider this example.
String temp = "abc"; // line1
String s = new String("abc"); // line2
In this case "abc" is not recreated. s will point to "abc" that was created at line 1.
sujith in comment : But in that case i do not see any difference between String temp ="abc" and String temp = new String("abc").
In line 1 a new "abc" will be created in heap. And a new String object will be created and added into the stack. And in line2 a new object of String will be created which will be referring to the "abc" that was created at line1 in heap. To better understand what thing goes to stack and what goes to heap visit here.
Yes it does. To optimize memory use, it does so.
In case you create another variable with same value "abc",
new variable will still point to earlier rather than creating a new one.
Somehow it is trying not to create two equal objects

Should we use String.intern in jdk 7 and +

I dont thnk i should ever use String.intern() in jdk7 and + ,Because of following reasons.
Java automatically interns String literals. This means that in many cases, the == operator appears to work for Strings in the same way that it does for ints or other primitive values.
Since interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh"); // why would i do this?
String s5 = new String("Rakesh").intern(); // looks stupid , better create like s1
s1,s2, s3 ,s4 point to same thing.
Your comments plz
String s3 = "Rakesh".intern();
This does nothing - the String object that represents the string literal is already in the string pool, so intern() does nothing here but just return the string that is already in the pool. It's the same as String s3 = "Rakesh";
String s4 = new String("Rakesh"); // why would i do this?
There is no reason ever to create a String object in this way, by passing it a string literal to the constructor. String objects are immutable and it is never necessary to explicitly create a copy of a string literal in this way.
String s5 = new String("Rakesh").intern(); // looks stupid , better create like s1
You already answered this yourself in the comment.
My advice: Forget about the intern() method - or keep it somewhere far away in the back of your mind. You don't need this method in 99,9% of the Java programs you are going to write. This method is only useful for very specific, rare occasions.
Just read the Java doc please.
When the intern method is invoked, if the pool already contains a
string equal to this String object as determined by
the equals(Object) method, then the string from the pool is
returned. Otherwise, this String object is added to the
pool and a reference to this String object is returned.

Java- Creating String object using new keyword

I know the difference between String literal and new String object and also know how it works internally.But my question is little bit advance of this.When we create String object using new keyword as
String str = new String("test");
In this case, we are passing a argument of String type.
My questions is where this string gets generated - Heap Or String constant pool Or somewhere else?
As up to my knowledge, this argument is a string literal so it should be in String constant pool.If is it so then what is use of intern method - only just link variable str to constant pool? because "test" would be available already.
Please clarify me, if I had misunderstood the concept.
The statement String str = new String("test"); creates a string object which gets stored on the heap like any other object. The string literal "test" that is passed as an argument is stored in the string constant pool.
String#intern() checks if a string constant is already available in the string pool. If there is one already it returns it, else it creates a new one and stores it in the pool. See the Javadocs:
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
Starting from JDK7, interned strings are stored on the heap. This is from the release notes of JDK7:
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.
Use of intern() :
public static void main(String[] args) throws IOException {
String s = new String(new char[] { 'a', 'b', 'c' }); // "abc" will not be added to String constants pool.
System.out.println(System.identityHashCode(s));
s = s.intern();// add s to String constants pool
System.out.println(System.identityHashCode(s));
String str1 = new String("hello");
String str2 = "hello";
String str3 = str1.intern();
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
System.out.println(System.identityHashCode(str3));
}
O/P :
1414159026
1569228633 --> OOPs String moved to String constants pool
778966024
1021653256
1021653256 --> "hello" already added to string pool. So intern does not add it again.

Why are equal java strings taking the same address? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
String object creation using new and its comparison with intern method
I was playing around with Strings to understand them more and I noticed something that I can't explain :
String str1 = "whatever";
String str2 = str1;
String str3 = "whatever";
System.out.println(str1==str2); //prints true...that's normal, they point to the same object
System.out.println(str1==str3); //gives true..how's that possible ?
How is the last line giving true ? this means that both str1 and str3 have the same address in memory.
Is this a compiler optimization that was smart enough to detect that both string literals are the same ("whatever") and thus assigned str1 and str3 to the same object ? Or am I missing something in the underlying mechanics of strings ?
Because Java has a pool of unique interned instances, and that String literals are stored in this pool. This means that the first "whatever" string literal is exactly the same String object as the third "whatever" literal.
As the Document Says:
public String intern()
Returns a canonical representation for the
string object. A pool of strings, initially empty, is maintained
privately by the class String.
When the intern method is invoked, if the pool already contains a
string equal to this String object as determined by the equals(Object)
method, then the string from the pool is returned. Otherwise, this
String object is added to the pool and a reference to this String
object is returned.
It follows that for any two strings s and t, s.intern() == t.intern()
is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are
interned. String literals are defined in ยง3.10.5 of the Java Language
Specification
Returns: a string that has the same contents as this string, but is
guaranteed to be from a pool of unique strings.
http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3
As the post says:
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool.
If you do:
String str1 = new String("BlaBla"); //In the heap!
String str2 = new String("BlaBla"); //In the heap!
then you're explicitly creating a String object through new operator (and constructor).
In this case you'll have each object pointing to a different storage location.
But if you do:
String str1 = "BlaBla";
String str2 = "BlaBla";
then you've implicit construction.
Two strings literals share the same storage if they have the same values, this is because Java conserves the storage of the same strings! (Strings that have the same value)
The javac compiler combines String literals which are the same in a given class file.
However at runtime, String literals are combined using the same approach as String.intern() This means even Strings in different class in different applications (in the same JVM which use the same object.

Categories