a quick and confusing question. If Class A and Class B have this inside them:-
String name="SomeName";
and both classes are instantiated, is it true that both instances refer to same memory location of variable "name" say when we do this objA.name or objB.name ? which has value "SomeName" and since String is immutable, several instances of both classes of same JVM use the same variable repeatedly? I read somewhere online that, unless there is
String example=new String("something");
is used, the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Note: I see several answers, which one do I count on, can someone conclude. Thank you all for your effort, appreciate it.
Yes, if you create two strings like:
String a = "Hello";
String b = "Hello";
They will be the exact same object. You can test it yourself by doing
System.out.println(a == b);
If they are the same object, then their internal reference to the character array will be exactly the same.
Now, if you did String c = "Hell" + "o";, it would not have the same reference since it would have been (internally) built using StringBuilder.
There is a lot of good information here.
The relevant sections has (Note: The following is copied from that web site):
As mentioned, there are two ways to construct a string: implicit construction by assigning a String literal or explicitly creating a String object via the new operator and constructor. For example,
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
Java has designed a special mechanism for keeping the String literals - in a so-called string common pool. If two String literals have the same contents, they will share the same storage locations inside the common pool. This approach is adopted to conserve storage for frequently-used strings. On the other hands, String object created via the new operator are kept in the heap. Each String object in the heap has its own storage just like any other object. There is no sharing of storage in heap even if two String objects have the same contents.
You can use the method equals() of the String class to compare the contents of two Strings. You can use the relational equality operator '==' to compare the references (or pointers) of two objects. Study the following codes:
s1 == s1; // true, same pointer
s1 == s2; // true, s1 and s1 share storage in common pool
s1 == s3; // true, s3 is assigned same pointer as s1
s1.equals(s3); // true, same contents
s1 == s4; // false, different pointers
s1.equals(s4); // true, same contents
s4 == s5; // false, different pointers in heap
s4.equals(s5); // true, same contents
Edit to add: Run this SSCE to test reference equality between two constant strings in to different classes:
class T {
String string = "Hello";
public static void main(String args[]) {
T t = new T();
T2 t2 = new T2();
System.out.println(t.string == t2.string);
}
}
class T2 {
String string = "Hello";
}
prints out true.
If "something" is literally hard-coded into your source code, then the two variables will point to the same in-memory String object.
Per the Java spec, a string literal (one that's defined as a literal in the byte codes) is "interned", so that any reference to that literal will obtain the exact same pointer, even if the reference is to an identical literal in an entirely separate class.
A string constructed at runtime (eg, "abc" + "xyz" or new String("abc")) will not be interned, and so the pointer will generally be unique. (But note that an optimizing compiler may combine "abc" + "xyz" into the single literal "abcxyz", resulting in an interned value.)
the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Strings, like other object are reclaimed when a GC is performed and there is no strong reference to it. Even intern'ed Strings can be cleaned up when they are no longer used.
I would add one more detail to all the solutions above. String interning is just an optimization of Java/C# compiler. It's not good to rely on it as it can be turned off in both cases.
It may also behave differently in different compilers/VM's implementations
Related
If we have a String s = "Hello" It will create string "Hello" in string pool and some reference is pointing to string s what if I change s="World" .In string pool it will create new String "World" and now my reference is pointing to World. What will happen to "Hello" String?
From the documentation of String:
... String objects are immutable ...
String-constants known at compile-time are also treated specially. They are stored in a constant pool. All "equal" compile-time String-constant reference the same String-object. This is the reason why
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2);
will print true. There are some other interesting examples. I wrote an Ideone example a while back that demonstrates some of those interesting cases.
When one re-assings a value to some non-primitive type variable s, the old object still exists on the heap (as long as the Garbage Collector does not deem it eligible for collection). What is changed is where the variable s is referencing. In the case presented, a second String-constant is created at compile-time and s then references the second constant.
String objects are immutable, so what happens with your second assignment is only an object reference update.
String literal objects (like "Hello" and "World") will be referenced from Java's String pool (they are interned). As this counts as a reference, the "Hello" object will not be garbage collected after your reassignment. That will only happen if the code itself becomes unreachable (e.g. if the entire class was loaded dynamically and its class loader becomes now unreachable).
I was trying to understand String#intern method. Now it has caused even more confusion.
package com;
public class Main {
public static void main(String[] args) {
String s1 = new String("GFG"); // Line-1
String s2 = s1.concat("GFG"); // Line-2
s2.intern(); // Line-3
String s4 = "GFGGFG"; // Line-4
// s2.intern(); // Line -5
System.out.println(s2 == s4);
}
}
The above code prints true. If I comment line 3 and uncomment line 5 it is printed false.
For line 3 the SCP is checked and the String is added to SCP.
But how did s2 equals to s4 in that case ?
s2 is still referencing to an object in heap which is pointing to SCP constant. Right ?
Can anyone please explain what is happening ? I've gone through different SO questions, but was not able to understand it still.
EDIT
I'm just trying to understand the intern method. I know the difference b/w == and equals and the latter is preferred.
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.
In simple words, Intern is responsible to make exact copy of contents in memory (string constant pool). Memory will be shared for all copied contents.
By applying String.intern() on a couple of strings will ensure that all strings having same contents share same memory. For example, if a name ‘Amy’ appears 100 times, by interning you ensure only one ‘Amy’ is actually allocated memory.
To prove it, we can use an operator == (used to compare reference) and equals method (to compare content).
public class InternExample{
public static void main(String args[]){
String s1=new String("hello");
String s2="hello";
String s3=s1.intern();//returns string from pool, now it will be same as s2
System.out.println(s1==s2);//false because reference variables are pointing to different instance
System.out.println(s2==s3);//true because reference variables are pointing to same instance
System.out.println(s2.equals(s3));//true because content are same
}}
Output:
false
true
true
Explanation:
Case-1: s1 and s2 has same content but pointing to different reference in memory as new String always create new reference so it is false.
Case-2: s3 is interned or copied from s1 and pointing to same reference in memory as intern function just make a copy and keep same reference so it is true.
Case-3: s2 and s3 has same content
It is very simple ... on the surface.
If you would have written:
s2 = s2.intern();
Then the location is irrelevant, always yielding s2 == s4.
What happens without the assignment seems a miracle for retrieving s2.
The JVM exchanging the string of s2 under the hood.
(Disassembly with javap -c did not show me something special.)
As intern is native, slow,
and the JVM is involved, I am not willing to dive further in this esoteric subject of String interning; pure speculations what could be happening.
But definitely baffling, an interesting issue.
I'm aware about string pool in JVM and difference between literals and string objects. I know that literals are automatically interned, but what is the purpose of this line then:
public static final String PARAMETER = "value".intern();
On my question I always find a ton of text which explains me the same with emphasis on the difference between literals and objects and mention that literals already interned. Therefore, I'd like to know about underlyings of using that tricky line with intern() over literal.
The main benefit of that type of code is to prevent compile-time constants from being inlined.
For instance, suppose you have a constant in one class and you have many other classes refer to that constant. Normally if you change the constant value, you'd need to recompile all the classes involved. Using intern() on the field will prevent inlining of the constant and means it would be sufficient to recompile just your constant class. In theory this approach would have inferior performance, although I have no idea how significant that might be.
This SO question covers the same topic and is a useful read.
To prevent compile time inlining
The only use case I can think of is to prevent it from being considered as compile time constant, so that it prevents inlining.
Now one reason can be that someone can change the value using Reflection, which will only work if the string is declared like that.
Also it allows you to change the class file containing constant as told by #Duncan in his answer. That is a good reason too.
How does that work?
When you declare String as public static final String CONST = "abc";, then it is a compile time constant and will be inlined in the class using that constant.
class A{
private void foo(){
String newString = CONST + someDynamicValue;
}
}
After compiling this, if you decompile the class you will find
class A{
private void foo(){
String newString = "abc" + someDynamicString;
}
}
But when you declare it with .intern() or any other method, then it cannot be considered as compile time constant and every time the value will be fetched from the class. Java does this to be efficient.
Example from #Marko's comment:
the SWT library uses a similar trick to stop from inlining int
constants, and the only reason is to be consistent with respect to
upgrading the SWT library
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()
Using your example:
String s1 = "Shoaib";
String s2 = "Shoaib";
String s3 = "Shoaib".intern();
String s4 = new String("Shoaib");
String s5 = new String("Shoaib").intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
if ( s1 == s4 ){
System.out.println("s1 and s4 are same" ); // 3.
}
if ( s1 == s5 ){
System.out.println("s1 and s5 are same" ); // 4.
}
will return:
s1 and s2 are same
s1 and s3 are same
s1 and s5 are same
Explaination in simple words:
->In String pooled region if suppose we have "Shoaib" as String whose reference is say 2020
->Now Any object you create by new String("Shoaib") will point to another reference say 3030
->But if you want to assign reference of "Shoaib" in String pooled region to new String("Shoaib") then we use intern() on it.
So above you asked that "value".intern() which doesn't make any sense in case of interning.
The intern() is used to access reference ID of your String Constant Pool.
It is possible that your variable may contain the same value so, we do not need to allocate it again.
We just use intern() to check it is already in String Constant Pool or not ?
If it is not in pool then just JVM allocate in pool area and return it reference ID & We used to share same data member and benefit is that we use same memory.
The purpose of this line
public static final String PARAMETER = "value".intern();
is just used to check from string constant pool. If it available then it's return not again added in pool.
This question already has answers here:
What is the difference between "text" and new String("text")?
(13 answers)
Closed 2 years ago.
String s="hi";
String s1=new String("hi");
In memory perspective, where are s and s1 stored? whether it is in heap memory or stack.
And s points "hi" and s1 points to memory location of where hi exists?
Please help?
Consider following
String s = "hi";
String s1 = new String("hi");
variable s will refer to the string literal hi that is referenced from String constant pool and if there are some more variables like s2 = "hi", then s and s2 will refer to same object.
String s1 = new String("hi");
This will create a new String at runtime.
In first case ,all the strnig literals are created when class is loaded in JVM
In seconds case, string objects are created when new String() is executed.
You can find a good tutorial about string constant pool at following link
http://www.thejavageek.com/2013/06/19/the-string-constant-pool/
String s="hi";
This statements creates the String object containing "hi" on the String pool.
String s1=new String("hi");
This statement creates a String object containing "hi" on the heap memory and a copy of it on StringPool (if "Hi" is not contained in stringPool).But here, S will point to the object on heap.
At class loading time, all String literals will be placed in pool. When you use new String("hi") an object will be created on heap. s and s1 are reference variables , it should reside in the method call stack ! The string literal "hi" will be handled by the JVM, by creating a String object on the heap, and having a reference to it from the String pool. The new operator merely takes the string object, whose reference is passed in the constructor, and create a new object. It just so happens that the string being passed to the constructor is a literal.
"hi" is a String literal. This gets created once in the String Constant Pool. In Java 7 that's in the Heap with other objects, but prior to that it was created in the Perm-Gen
String s = "hi";
String s1 = new String("hi");
new String("hi") creates a new String object on the heap, separate from the existing one.
s and s1 are references to the two separate objects. References themselves actually live on the stack, even though they point to objects in the heap.
s and s1 are just references to the strings, therefore they will be stored on the stack, unlike the string instances that are referenced by s and s1. In this case the value that s refers to will be put in the string pool whereas the value refered by s1 won't. Why? because the constructor of a string has been used to make that string. Only literals are pooled, and even if you chose those literals to be concatenations of other literals ( for example, if you have made String s2 = "h" + "i" then s and s2 would point to the same instance of a string that was stored in the string pool).
This leads to a little trap though: because pooled strings point to the same object it is tempting to use == operator instead of equals method to compare strings, which is just dangerous, because there are scenarios where == is the same as equals() but there are a lot more where == will have a different result than the equals() method.
Above answers are correct but shouldn't you use String *s1 = new String("hi") in place ofString s1 = new String("hi") ,as call to new will be returning a pointer to the string object.
I am fairly new to C++. Excuse me, if I am wrong.
PS: I am using the gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).
According to me when we create String using literal like String s="hello"
s object will reference the String "hello" that is stored in the String Constant pool.
If we will create the new String using New keyword like String s = new String("hello") then in this case two object is created. object s referenced the another object that is stored in the normal heap area and this object will referenced the String Hello that is stored in the String constant pool.
For more details please follow the link:-http://www.javatpoint.com/java-string
String s1 = new String("string");
String s2 = new String("string");
String s3 = "string";
String s4 = "string";
System.out.println(s1 == s2); //FALSE
System.out.println(s2.equals(s1)); //TRUE
System.out.println(s3 == s4); //TRUE
System.out.println(s3.equals(s4)); //TRUE
What is the difference between creation of s1 and s3 ?
Please let me know
In String we are having only String object then why it treats this two differently.
s1 and s2 are having different memory address while s3 and s4 has same memory address.
why it works based on new operator.?
The String objects that represent string literals in your Java source code are added to a shared String pool when the classes that defines them are loaded1. This ensures that all "copies" of a String literal are actually the same object ... even if the literal appears in multiple classes. That is why s3 == s4 is true.
By contrast, when you new a String, a distinct new String object is created. That is why s1 == s2 is false. (This is a fundamental property of new. It is guaranteed to create and return a new object ... if it completes normally.)
However, in either case, the strings will have the same characters, and that is why equals is returning true.
While it is important to understand what is going on, the real lesson is that the correct way to compare Java strings is to use equals and not ==.
If you want to arrange that your String objects can be tested for equality using ==, you can "intern" them using the String.intern method. However, you have to do this consistently ... and interning is an expensive process in various respects ... so it is generally not a good idea.
1 - Actually, it is a bit more complicated than that. They objects get added to the pool at some time between class loading and first use of the literals. The precise timing is unspecified and JVM implementation dependent. However it is guaranteed to happen just once, and before any application code sees the String object reference corresponding to the literal.
s1 is a new String object that does not belong to a part of any pooled instance. s3 is an instance of a string that comes from a pool. Lookup java String pool. Take a look at the related intern() method on String.
The concept is not unique to java. String interning is supported in other languages. On that related note, pooling frequently used objects follows the flyweight pattern and is not limited to Strings. Take a look at Integer.valueOf(). Integers have a constant pool of their own too.
The JVM has an automatic optimisation. Unless you specifically create a new String object, and another String object already exists with the same value, the JVM automatically assumes that a new object is not a necessity, and will assign you a pointer to the equal String object that already exists.
Essentially, when you use the second option, this is what happens:
Step 1
First Object is created no problem.
Step 2
Before the second object is created, the String pool is checked for a value.
If that value currently exists, then there is no need to create a new object. It just returns the reference to the String object.
Step 3
Instead of being assigned a new Object, it is simply given a reference to the object made in step 1. This is to save memory.
This happens because the new operator forces creation of a new instance of String, while in the second case, as String is an immutable class, the JVM provides you with the same String instance for both variables to save memory. As there is no chance one of such objects will change causing the second one change as well (immutable, remember?) this is OK.