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.
Related
String S1="He";
String S2="llow";
String S3="Hellow";
String S4="He"+"llow";
String S5=S1+S2;
System.out.println(S3==S4); // prints true
System.out.println(S5==S3); // prints false
System.out.println(S5==S4); // prints false
why S5 is not referring object from constant pool?
since S3 and S4 are in pool thats why giving true on S3==S4
but in case of S5==S3 & S5==S4 result is false,means S5 is not in pool.
The strings s1 through s4 are all compile time constants.
The compiler calculates "He" + "llow" during compile time, and consults the string pool as to whether the result is already there, and puts it there if it doesn't.
But the calculation of s1 + s2 is not done in compile time, and therefore its result is not interned. Why? Because in theory, another thread could change the value of s1 or s2 so by the time we get to this instruction in the code, it may set s2 to "foo", so the result becomes "Hefoo".
You, as the author, may know that no thread will be doing that and that these are local variables anyway, but the compiler doesn't.
If you change your definitions to:
final String s1="He";
final String s2="llow";
final String s3="Hellow";
final String s4="He"+"llow";
final String s5=s1+s2;
Then indeed, the result of s5 == s3 will be true! Why? Because the final keyword lets the compiler know that these strings are not going to be replaced, they are the final value of these variables. So it can calculate it in compile time and take the result that is already in the pool.
from JLS
https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5
Strings computed by constant expressions (§15.28) are computed at
compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and
therefore distinct.
In the case of String S4, you're doing compile time concatenation,
String S4="He"+"llow";
therefore, it refers to the same object as S3
however , S1+S2 is a concatenation at run time , therefore , it refers to separate String object than S3 even though S1 + S2 and S3 are meaningfully equivalent .
i.e (S1+S2).equals(S3) would return true
you can put a String in pool using intern method
Since in String S4="He"+"llow"; Object create in pool and this is compile time constant same as S3="Hellow"; both are same object in pool but S5 created in heap at run time.
String literals that are concatenated are entered into the String pool. A String resulting from concatenation of variables however is not. That is why S3 is equal to S4 but not S5. They are not referring to the same object. However, (although I haven't tested this out) S5.equals(S4) should return true.
System.out.println(S3==S4);//true
Because S4 = "He"+"llow"; is optimised by the compiler and lead to the same string as "Hellow" which is shared with S3, hence S4 and S3 have the same reference.
System.out.println(S5==S3);//false
Because S5 and S3 are 2 distinct objects with different references.
System.out.println(S5==S4);//false
Same thing as before.
When you compare objects, you usually want to compare the content (with equals() and not the address/reference (with ==).
In general the compiler interns constant strings - even the ones created by a concatenation. That is why S3 and S4 are the same object.
S5 however is evaluated at runtime, that is why it creates a new object, distinct (but equal to) S4. If you put it into the string pool yourself, you will again get the same object as S4, so S5.intern() == S4 would be true.
Note that S5 not being the same as S4 is not guaranteed. A more optimizing compiler could put it into the string pool at compile time.
compare string in java use equals
in a java objects == compare memory adresses
String S5=S1+S2;
S1+S2 return new string object
some objet have distinct memory adress
you may compare use equals
System.out.println(S5.equals(S4));
if you concat many string objects use StringBuilder
they fowing fasted and use minimum memory
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.
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
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.
String s1 = "BloodParrot is the man";
String s2 = "BloodParrot is the man";
String s3 = new String("BloodParrot is the man");
System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));
// output
true
true
false
true
Why don't all the strings have the same location in memory if all three have the same contents?
Java only automatically interns String literals. New String objects (created using the new keyword) are not interned by default. You can use the String.intern() method to intern an existing String object. Calling intern will check the existing String pool for a matching object and return it if one exists or add it if there was no match.
If you add the line
s3 = s3.intern();
to your code right after you create s3, you'll see the difference in your output.
See some more examples and a more detailed explanation.
This of course brings up the very important topic of when to use == and when to use the equals method in Java. You almost always want to use equals when dealing with object references. The == operator compares reference values, which is almost never what you mean to compare. Knowing the difference helps you decide when it's appropriate to use == or equals.
You explicitly call new for s3 and this leaves you with a new instance of the string.
Creating a String is actually a fast process. Trying to find any previously created String will be much slower.
Consider what you need to do to make all Strings interned. You need to search a set of all previously constructed Strings. Note this must be done in a thread-safe manner, which adds overhead. Because you don't want this to leak, you need to be using some form of (thread-safe) non-strong references.
Of course, you can't implement Java like this because the library unfortunately exposes constructors for Strings and most other immutable value objects.
The new keyword always makes a new string.
More detail here.
Why don't all the strings have the same location in memory if all three have the same contents?
Because they are different strings with same content!
There is a method called String.intern which, essentially, takes all Strings that are the same and puts them into a hash table (I am sort of lying, but for this it is the concept that matters, not the reality).
String s1 = "BloodParrot is the man";
String s2 = "BloodParrot is the man";
String s3 = new String("BloodParrot is the man").intern();
System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));
should have them all being "true". This is because (and I am lying a bit here again, but it still only matters for the concept not reality) String s1 = "BloodParrot is the man"; is done something like String s1 = "BloodParrot is the man".intern();