Related
According to String#intern(), intern method is supposed to return the String from the String pool if the String is found in String pool, otherwise a new string object will be added in String pool and the reference of this String is returned.
So i tried this:
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".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.
}
I was expecting that s1 and s3 are same will be printed as s3 is interned, and s1 and s2 are same will not be printed. But the result is: both lines are printed. So that means, by default String constants are interned. But if it is so, then why do we need the intern method? In other words when should we use this method?
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 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").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
In all the cases besides of s4 variable, a value for which was explicitly created using new operator and where intern method was not used on it's result, it is a single immutable instance that's being returned JVM's string constant pool.
Refer to JavaTechniques "String Equality and Interning" for more information.
On a recent project, some huge data structures were set up with data that was read in from a database (and hence not String constants/literals) but with a huge amount of duplication. It was a banking application, and things like the names of a modest set (maybe 100 or 200) corporations appeared all over the place. The data structures were already large, and if all those corp names had been unique objects they would have overflowed memory. Instead, all the data structures had references to the same 100 or 200 String objects, thus saving lots of space.
Another small advantage of interned Strings is that == can be used (successfully!) to compare Strings if all involved strings are guaranteed to be interned. Apart from the leaner syntax, this is also a performance enhancement. But as others have pointed out, doing this harbors a great risk of introducing programming errors, so this should be done only as a desparate measure of last resort.
The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limited, depending on the Java implementation. It's best done when you're dealing with a known reasonable number of Strings with many duplications.
I want to add my 2 cents on using == with interned strings.
The first thing String.equals does is this==object.
So although there is some miniscule performance gain ( you are not calling a method), from the maintainer point of view using == is a nightmare, because some interned strings have a tendency to become non-interned.
So I suggest not to rely on special case of == for interned strings, but always use equals as Gosling intended.
EDIT: interned becoming non-interned:
V1.0
public class MyClass
{
private String reference_val;
...
private boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
In version 2.0 maintainer decided to make hasReferenceVal public, without going into much detail that it expects an array of interned strings.
V2.0
public class MyClass
{
private String reference_val;
...
public boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
Now you have a bug, that may be very hard to find, because in majority of cases array contains literal values, and sometimes a non-literal string is used. If equals were used instead of == then hasReferenceVal would have still continue to work. Once again, performance gain is miniscule, but maintenance cost is high.
Learn Java String Intern - once for all
Strings in java are immutable objects by design. Therefore, two string objects even with same value will be different objects by default. However, if we wish to save memory, we could indicate to use same memory by a concept called string intern. The below rules would help you understand the concept in clear terms:
String class maintains an intern-pool which is initially empty. This pool must guarantee to contain string objects with only unique values.
All string literals having same value must be considered same memory-location object because they have otherwise no notion of distinction. Therefore, all such literals with same value will make a single entry in the intern-pool and will refer to same memory location.
Concatenation of two or more literals is also a literal. (Therefore rule #2 will be applicable for them)
Each string created as object (i.e. by any other method except as literal) will have different memory locations and will not make any entry in the intern-pool
Concatenation of literals with non-literals will make a non-literal. Thus, the resultant object will have a new memory location and will NOT make an entry in the intern-pool.
Invoking intern method on a string object, either creates a new object that enters the intern-pool or return an existing object from the pool that has same value. The invocation on any object which is not in the intern-pool, does NOT move the object to the pool. It rather creates another object that enters the pool.
Example:
String s1=new String ("abc");
String s2=new String ("abc");
If (s1==s2) //would return false by rule #4
If ("abc" == "a"+"bc" ) //would return true by rules #2 and #3
If ("abc" == s1 ) //would return false by rules #1,2 and #4
If ("abc" == s1.intern() ) //would return true by rules #1,2,4 and #6
If ( s1 == s2.intern() ) //wound return false by rules #1,4, and #6
Note: The motivational cases for string intern are not discussed here. However, saving of memory will definitely be one of the primary objectives.
String literals and constants are interned by default.
That is, "foo" == "foo" (declared by the String literals), but new String("foo") != new String("foo").
you should make out two period time which are compile time and runtime time.for example:
//example 1
"test" == "test" // --> true
"test" == "te" + "st" // --> true
//example 2
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true
in the one hand,in the example 1,we find the results are all return true,because in the compile time,the jvm will put the "test" to the pool of literal strings,if the jvm find "test" exists,then it will use the exists one,in example 1,the "test" strings are all point to the same memory address,so the example 1 will return true.
in the other hand,in the example 2,the method of substring() execute in the runtime time,
in the case of "test" == "!test".substring(1),the pool will create two string object,"test"
and "!test",so they are different reference objects,so this case will return false,in the case of "test" == "!test".substring(1).intern(),the method of intern() will put the ""!test".substring(1)" to the pool of literal strings,so in this case,they are same reference objects,so will return true.
http://en.wikipedia.org/wiki/String_interning
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.
Interned Strings avoid duplicate Strings. Interning saves RAM at the expense of more CPU time to detect and replace duplicate Strings. There is only one copy of each String that has been interned, no matter how many references point to it. Since Strings are immutable, if two different methods incidentally use the same String, they can share a copy of the same String. The process of converting duplicated Strings to shared ones is called interning.String.intern() gives you the address of the canonical master String. You can compare interned Strings with simple == (which compares pointers) instead of equals which compares the characters of the String one by one. Because Strings are immutable, the intern process is free to further save space, for example, by not creating a separate String literal for "pot" when it exists as a substring of some other literal such as "hippopotamus".
To see more http://mindprod.com/jgloss/interned.html
String s1 = "Anish";
String s2 = "Anish";
String s3 = new String("Anish");
/*
* When the intern method is invoked, if the pool already contains a
* string equal to this String object as determined by the
* 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.
*/
String s4 = new String("Anish").intern();
if (s1 == s2) {
System.out.println("s1 and s2 are same");
}
if (s1 == s3) {
System.out.println("s1 and s3 are same");
}
if (s1 == s4) {
System.out.println("s1 and s4 are same");
}
OUTPUT
s1 and s2 are same
s1 and s4 are same
String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();
if (p1 == p2)
System.out.println("p1 and p2 are the same");
if (p1 == p3)
System.out.println("p1 and p3 are the same");
if (p1 == p4)
System.out.println("p1 and p4 are the same");
if (p1 == p5)
System.out.println("p1 and p5 are the same");
if (p1 == p6)
System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
System.out.println("p1 and p7 are the same");
When two strings are created independently, intern() allows you to compare them and also it helps you in creating a reference in the string pool if the reference didn't exist before.
When you use String s = new String(hi), java creates a new instance of the string, but when you use String s = "hi", java checks if there is an instance of word "hi" in the code or not and if it exists, it just returns the reference.
Since comparing strings is based on reference, intern() helps in you creating a reference and allows you to compare the contents of the strings.
When you use intern() in the code, it clears of the space used by the string referring to the same object and just returns the reference of the already existing same object in memory.
But in case of p5 when you are using:
String p5 = new String(p3);
Only contents of p3 are copied and p5 is created newly. So it is not interned.
So the output will be:
p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "test";
String s2 = new String("test");
System.out.println(s1==s2); //false
System.out.println(s1==s2.intern()); //true --> because this time compiler is checking from string constant pool.
}
string intern() method is used to create an exact copy of heap string object in string constant pool. The string objects in the string constant pool are automatically interned but string objects in heap are not. The main use of creating interns is to save the memory space and to perform faster comparison of string objects.
Source : What is string intern in java?
As you said, that string intern() method will first find from the String pool, if it finds, then it will return the object that points to that, or will add a new String into the pool.
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hello".intern();
String s4 = new String("Hello");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//true
System.out.println(s1 == s4.intern());//true
The s1 and s2 are two objects pointing to the String pool "Hello", and using "Hello".intern() will find that s1 and s2. So "s1 == s3" returns true, as well as to the s3.intern().
By using heap object reference if we want to get corresponding string constant pool object reference, then we should go for intern()
String s1 = new String("Rakesh");
String s2 = s1.intern();
String s3 = "Rakesh";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true
Pictorial View
Step 1:
Object with data 'Rakesh' get created in heap and string constant pool. Also s1 is always pointing to heap object.
Step 2:
By using heap object reference s1, we are trying to get corresponding string constant pool object referenc s2, using intern()
Step 3:
Intentionally creating a object with data 'Rakesh' in string constant pool, referenced by name s3
As "==" operator meant for reference comparison.
Getting false for s1==s2
Getting true for s2==s3
Hope this help!!
if i create a string object as
String s=new String("Stackoverflow");
will String object created only in heap, or it also makes a copy in String constant pool.
Thanks in advance.
You only get a string into the constant pool if you call intern or use a string literal, as far as I'm aware.
Any time you call new String(...) you just get a regular new String object, regardless of which constructor overload you call.
In your case you're also ensuring that there is a string with contents "Stackoverflow" in the constant pool, by the fact that you're using the string literal at all - but that won't add another one if it's already there. So to split it up:
String x = "Stackoverflow"; // May or may not introduce a new string to the pool
String y = new String(x); // Just creates a regular object
Additionally, the result of a call to new String(...) will always be a different reference to all previous references - unlike the use of a string literal. For example:
String a = "Stackoverflow";
String b = "Stackoverflow";
String x = new String(a);
String y = new String(a);
System.out.println(a == b); // true due to constant pooling
System.out.println(x == y); // false; different objects
Finally, the exact timing of when a string is added to the constant pool has never been clear to me, nor has it mattered to me. I would guess it might be on class load (all the string constants used by that class, loaded immediately) but it could potentially be on a per-method basis. It's possible to find out for one particular implementation using intern(), but it's never been terribly important to me :)
In this case you are constructing an entirely new String object and that object won't be shared in the constant pool. Note though that in order to construct your new String() object you actually passed into it a String constant. That String constant is in the constants pool, however the string you created through new does not point to the same one, even though they have the same value.
If you did String s = "Stackoverflow" then s would contain a reference to the instance in the pool, also there are methods to let you add Strings to the pool after they have been created.
The new String is created in the heap, and NOT in the string pool.
If you want a newly create String to be in the string pool you need to intern() it; i.e.
String s = new String("Stackoverflow").intern();
... except of course that will return the string literal object that you started with!!
String s1 = "Stackoverflow";
String s2 = new String(s1);
String s3 = s2.intern();
System.out.println("s1 == s2 is " + (s1 == s2));
System.out.println("s2 == s3 is " + (s2 == s3));
System.out.println("s1 == s3 is " + (s1 == s3));
should print
s1 == s2 is false
s2 == s3 is false
s1 == s3 is true
And to be pedantic, the String in s is not the String that was created by the new String("StackOverflow") expression. What intern() does is to lookup the its target object in the string pool. If there is already a String in the pool that is equal(Object) to the object being looked up, that is what is returned as the result. In this case, we can guarantee that there will already be an object in the string pool; i.e. the String object that represents the value of the literal.
A regular java object will be created in the heap, and will have a reference s type of String. And, there will be String literal in String Constant Pool. Both are two different things.
My answer is YES!
Check the following code first:
String s0 = "Stackoverflow";
String s1 = new String("Stackoverflow");
String s2 = s1.intern();
System.out.println(s0 == s1);
System.out.println(s1 == s2 );
System.out.println(s0 == s2);
//OUTPUT:
false
false
true
s0 hold a reference in the string pool, while new String(String original) will always construct a new instance. intern() method of String will return a reference in the string pool with the same value.
Now go back to your question:
Will String object created only in heap, or it also makes a copy in String constant pool?
Since you already wrote a string constant "Stackoverflow" and pass it to your String constructor, so in my opinion, it has the same semantic as:
String s0 = "Stackoverflow";
String s1 = new String(s0);
which means there will be a copy in String constant pool when the code is evaluated.
But, if you construct the String object with following code:
String s = new String("StackoverflowSOMETHINGELSE".toCharArray(),0,13);
there won't be a copy of "Stackoverflow" in constant pool.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
difference between string object and string literal
Hello,
Foremost, let’s come up with Java facts with String
Strings are immutable
My Question - If Strings are immutable then below statement should have compilation error!
String str = "xyz";
or
String str = new String("xyz");
str = "abc"; //COMPILATION ERROR
or
str = new String("abc"); //COMPILATION ERROR
What is the difference between below instantiation ?
String str = "xyz";
and
String str = new String("xyz");
Amit.
Strings are immutable means you can't do something like str[1] = 'x' i.e you cannot change the content of the string.
This will answer your second question.
Strings are immutable, so you cannot change the contents of a string.
In the following code:
String str = "xyz";
str = "abc";
you're not changing the contents of a String instance, but rather assigning a new String instance to the variable str. That is, if you do:
String str = "xyz";
String otherStr = str;
String str = "abc";
Then otherStr will remain the same. So you're not actually changing the object that str points to.
As for your second question
String str = "xyz";
takes the a String-object with value "xyz" from the String pool, while
String str = new String("xyz");
instantiates a new object.
That is, if you do
String a = "xyz", b = "xyz";
you will have a == b, while if you do
String a = new String("xyz"), b = new String("xyz");
this will not be the case.example
For more information, see:
What is String literal pool?
Questions about Java's String pool
Strings are immutable. String references are not. That's the distinction.
So:
String str = "abc";
str is a variable, referring to an immutable string "abc". Now if I do:
str = "def";
str is still a variable, referring to a different immutable string ("def"). I can change what str points to all I want, str is a variable. I can't change the actual content of any string (because Java's strings are immutable, by design). Whenever you do something that would seem to modify the string (say, toUpperCase), what it's actually doing is creating a new string with a copy of the old string's contents, modified in the way described.
The point of having strings be immutable is that I know that if I have a reference to a string, that string can never change. This is a very useful guarantee when passing strings around. If we didn't have this guarantee, we'd be copying strings all the time just to protect ourselves from someone modifying them. For instance, consider a standard setter function for a name property:
void setName(String n) {
this.name = n;
}
If strings weren't immutable, we'd have to do this:
void setName(String n) {
this.name = new String(n); // Blech, duplication
}
...so that we know our copy of the string won't change in ways we don't expect it to. This would result in a lot of duplication of string data in memory, most of it unnecessary, and so the designers of Java quite intelligently decided that strings would be immutable, and any changes you might want would create a new string rather than modifying the old one in-place. (You can get modify-in-place behavior for those situations that really warrant it by using char[] instead.)
Regarding your separate question about the difference between str = "abc"; and str = new String("abc"), the difference is that the latter (using the constructor) is guaranteed to return a new reference, whereas the former is not. E.g.:
String a = "abc";
String b = "abc";
String c = new String("abc");
a == b (checking whether the references match, not the strings) will be true, because literal strings are interned. a == c is guaranteed to be false, because we used the constructor for c. a.equals(b) and a.equals(c) will both be true, because a, b, and c all refer to equivalent strings.
If Strings are immutable then below
statement should have compilation
error!
You are misunderstanding the immutability concept. Look at Prasoon's answer.
String immutability means you cannot alter the contents inside the string.
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Here both a and b both string literals refer the same object.
What is the difference between two
instantiations ?
String a = "hello";
String b = "hello";
System.out.println(a==b); // returns true.
Both refer to same String literal.
String a = new String("hello");
String b = new String("hello");
System.out.println(a==b); // returns false.
Two different String Objects are created.
String str = "xyz";
is an internal cached string instance.
String str = new String("xyz");
is a new object not instanciated from the cache
As side fact notice the following behaviour ...
"xyz" == "xyz" evals true
new String("xyz") == new String("xyz") evals false
new String("xyz").equals(new String("xyz")) evals true
notice also that == in Java compares object references.
According to String#intern(), intern method is supposed to return the String from the String pool if the String is found in String pool, otherwise a new string object will be added in String pool and the reference of this String is returned.
So i tried this:
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".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.
}
I was expecting that s1 and s3 are same will be printed as s3 is interned, and s1 and s2 are same will not be printed. But the result is: both lines are printed. So that means, by default String constants are interned. But if it is so, then why do we need the intern method? In other words when should we use this method?
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 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").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
In all the cases besides of s4 variable, a value for which was explicitly created using new operator and where intern method was not used on it's result, it is a single immutable instance that's being returned JVM's string constant pool.
Refer to JavaTechniques "String Equality and Interning" for more information.
On a recent project, some huge data structures were set up with data that was read in from a database (and hence not String constants/literals) but with a huge amount of duplication. It was a banking application, and things like the names of a modest set (maybe 100 or 200) corporations appeared all over the place. The data structures were already large, and if all those corp names had been unique objects they would have overflowed memory. Instead, all the data structures had references to the same 100 or 200 String objects, thus saving lots of space.
Another small advantage of interned Strings is that == can be used (successfully!) to compare Strings if all involved strings are guaranteed to be interned. Apart from the leaner syntax, this is also a performance enhancement. But as others have pointed out, doing this harbors a great risk of introducing programming errors, so this should be done only as a desparate measure of last resort.
The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limited, depending on the Java implementation. It's best done when you're dealing with a known reasonable number of Strings with many duplications.
I want to add my 2 cents on using == with interned strings.
The first thing String.equals does is this==object.
So although there is some miniscule performance gain ( you are not calling a method), from the maintainer point of view using == is a nightmare, because some interned strings have a tendency to become non-interned.
So I suggest not to rely on special case of == for interned strings, but always use equals as Gosling intended.
EDIT: interned becoming non-interned:
V1.0
public class MyClass
{
private String reference_val;
...
private boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
In version 2.0 maintainer decided to make hasReferenceVal public, without going into much detail that it expects an array of interned strings.
V2.0
public class MyClass
{
private String reference_val;
...
public boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
Now you have a bug, that may be very hard to find, because in majority of cases array contains literal values, and sometimes a non-literal string is used. If equals were used instead of == then hasReferenceVal would have still continue to work. Once again, performance gain is miniscule, but maintenance cost is high.
Learn Java String Intern - once for all
Strings in java are immutable objects by design. Therefore, two string objects even with same value will be different objects by default. However, if we wish to save memory, we could indicate to use same memory by a concept called string intern. The below rules would help you understand the concept in clear terms:
String class maintains an intern-pool which is initially empty. This pool must guarantee to contain string objects with only unique values.
All string literals having same value must be considered same memory-location object because they have otherwise no notion of distinction. Therefore, all such literals with same value will make a single entry in the intern-pool and will refer to same memory location.
Concatenation of two or more literals is also a literal. (Therefore rule #2 will be applicable for them)
Each string created as object (i.e. by any other method except as literal) will have different memory locations and will not make any entry in the intern-pool
Concatenation of literals with non-literals will make a non-literal. Thus, the resultant object will have a new memory location and will NOT make an entry in the intern-pool.
Invoking intern method on a string object, either creates a new object that enters the intern-pool or return an existing object from the pool that has same value. The invocation on any object which is not in the intern-pool, does NOT move the object to the pool. It rather creates another object that enters the pool.
Example:
String s1=new String ("abc");
String s2=new String ("abc");
If (s1==s2) //would return false by rule #4
If ("abc" == "a"+"bc" ) //would return true by rules #2 and #3
If ("abc" == s1 ) //would return false by rules #1,2 and #4
If ("abc" == s1.intern() ) //would return true by rules #1,2,4 and #6
If ( s1 == s2.intern() ) //wound return false by rules #1,4, and #6
Note: The motivational cases for string intern are not discussed here. However, saving of memory will definitely be one of the primary objectives.
String literals and constants are interned by default.
That is, "foo" == "foo" (declared by the String literals), but new String("foo") != new String("foo").
you should make out two period time which are compile time and runtime time.for example:
//example 1
"test" == "test" // --> true
"test" == "te" + "st" // --> true
//example 2
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true
in the one hand,in the example 1,we find the results are all return true,because in the compile time,the jvm will put the "test" to the pool of literal strings,if the jvm find "test" exists,then it will use the exists one,in example 1,the "test" strings are all point to the same memory address,so the example 1 will return true.
in the other hand,in the example 2,the method of substring() execute in the runtime time,
in the case of "test" == "!test".substring(1),the pool will create two string object,"test"
and "!test",so they are different reference objects,so this case will return false,in the case of "test" == "!test".substring(1).intern(),the method of intern() will put the ""!test".substring(1)" to the pool of literal strings,so in this case,they are same reference objects,so will return true.
http://en.wikipedia.org/wiki/String_interning
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.
Interned Strings avoid duplicate Strings. Interning saves RAM at the expense of more CPU time to detect and replace duplicate Strings. There is only one copy of each String that has been interned, no matter how many references point to it. Since Strings are immutable, if two different methods incidentally use the same String, they can share a copy of the same String. The process of converting duplicated Strings to shared ones is called interning.String.intern() gives you the address of the canonical master String. You can compare interned Strings with simple == (which compares pointers) instead of equals which compares the characters of the String one by one. Because Strings are immutable, the intern process is free to further save space, for example, by not creating a separate String literal for "pot" when it exists as a substring of some other literal such as "hippopotamus".
To see more http://mindprod.com/jgloss/interned.html
String s1 = "Anish";
String s2 = "Anish";
String s3 = new String("Anish");
/*
* When the intern method is invoked, if the pool already contains a
* string equal to this String object as determined by the
* 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.
*/
String s4 = new String("Anish").intern();
if (s1 == s2) {
System.out.println("s1 and s2 are same");
}
if (s1 == s3) {
System.out.println("s1 and s3 are same");
}
if (s1 == s4) {
System.out.println("s1 and s4 are same");
}
OUTPUT
s1 and s2 are same
s1 and s4 are same
String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();
if (p1 == p2)
System.out.println("p1 and p2 are the same");
if (p1 == p3)
System.out.println("p1 and p3 are the same");
if (p1 == p4)
System.out.println("p1 and p4 are the same");
if (p1 == p5)
System.out.println("p1 and p5 are the same");
if (p1 == p6)
System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
System.out.println("p1 and p7 are the same");
When two strings are created independently, intern() allows you to compare them and also it helps you in creating a reference in the string pool if the reference didn't exist before.
When you use String s = new String(hi), java creates a new instance of the string, but when you use String s = "hi", java checks if there is an instance of word "hi" in the code or not and if it exists, it just returns the reference.
Since comparing strings is based on reference, intern() helps in you creating a reference and allows you to compare the contents of the strings.
When you use intern() in the code, it clears of the space used by the string referring to the same object and just returns the reference of the already existing same object in memory.
But in case of p5 when you are using:
String p5 = new String(p3);
Only contents of p3 are copied and p5 is created newly. So it is not interned.
So the output will be:
p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "test";
String s2 = new String("test");
System.out.println(s1==s2); //false
System.out.println(s1==s2.intern()); //true --> because this time compiler is checking from string constant pool.
}
string intern() method is used to create an exact copy of heap string object in string constant pool. The string objects in the string constant pool are automatically interned but string objects in heap are not. The main use of creating interns is to save the memory space and to perform faster comparison of string objects.
Source : What is string intern in java?
As you said, that string intern() method will first find from the String pool, if it finds, then it will return the object that points to that, or will add a new String into the pool.
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hello".intern();
String s4 = new String("Hello");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//true
System.out.println(s1 == s4.intern());//true
The s1 and s2 are two objects pointing to the String pool "Hello", and using "Hello".intern() will find that s1 and s2. So "s1 == s3" returns true, as well as to the s3.intern().
By using heap object reference if we want to get corresponding string constant pool object reference, then we should go for intern()
String s1 = new String("Rakesh");
String s2 = s1.intern();
String s3 = "Rakesh";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true
Pictorial View
Step 1:
Object with data 'Rakesh' get created in heap and string constant pool. Also s1 is always pointing to heap object.
Step 2:
By using heap object reference s1, we are trying to get corresponding string constant pool object referenc s2, using intern()
Step 3:
Intentionally creating a object with data 'Rakesh' in string constant pool, referenced by name s3
As "==" operator meant for reference comparison.
Getting false for s1==s2
Getting true for s2==s3
Hope this help!!
This question already has answers here:
What is the difference between == and equals() in Java?
(26 answers)
Closed 6 years ago.
I switched lecturers today and he stated using a weird code to me. (He said it's better to use .equals and when I asked why, he answered "because it is!")
So here's an example:
if (o1.equals(o2))
{
System.out.println("Both integer objects are the same");
}
Instead of what I'm used to:
if (o1 == o2)
{
System.out.println("Both integer objects are the same");
}
What's the difference between the two. And why is his way (using .equals) better?
Found this on a quick search but I can't really make sense of that answer:
In Java, == always just compares two references (for non-primitives, that is) - i.e. it tests whether the two operands refer to the same object.
However, the equals method can be overridden - so two distinct objects can still be equal.
For example:
String x = "hello";
String y = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });
System.out.println(x == y); // false
System.out.println(x.equals(y)); // true
Additionally, it's worth being aware that any two equal string constants (primarily string literals, but also combinations of string constants via concatenation) will end up referring to the same string. For example:
String x = "hello";
String y = "he" + "llo";
System.out.println(x == y); // true!
Here x and y are references to the same string, because y is a compile-time constant equal to "hello".
The == operator compares if the objects are the same instance. The equals() oerator compares the state of the objects (e.g. if all attributes are equal). You can even override the equals() method to define yourself when an object is equal to another.
If you and I each walk into the bank, each open a brand new account, and each deposit $100, then...
myAccount.equals(yourAccount) is true because they have the same value, but
myAccount == yourAccount is false because they are not the same account.
(Assuming appropriate definitions of the Account class, of course. ;-)
== is an operator. equals is a method defined in the Object class
== checks if two objects have the same address in the memory and for primitive it checks if they have the same value.equals method on the other hand checks if the two objects which are being compared have an equal value(depending on how ofcourse the equals method has been implemented for the objects. equals method cannot be applied on primitives(which means that
if a is a primitive a.equals(someobject) is not allowed, however someobject.equals(a) is allowed).
== operator compares two object references to check whether they refer to same instance. This also, will return true on successful match.for example
public class Example{
public static void main(String[] args){
String s1 = "Java";
String s2 = "Java";
String s3 = new string ("Java");
test(Sl == s2) //true
test(s1 == s3) //false
}}
above example == is a reference comparison i.e. both objects point to the same memory location
String equals() is evaluates to the comparison of values in the objects.
public class EqualsExample1{
public static void main(String args[]){
String s = "Hell";
String s1 =new string( "Hello");
String s2 =new string( "Hello");
s1.equals(s2); //true
s.equals(s1) ; //false
}}
above example It compares the content of the strings. It will return true if string matches, else returns false.
In Java, when the “==” operator is used to compare 2 objects, it checks to see if the objects refer to the same place in memory. EX:
String obj1 = new String("xyz");
String obj2 = new String("xyz");
if(obj1 == obj2)
System.out.println("obj1==obj2 is TRUE");
else
System.out.println("obj1==obj2 is FALSE");
Even though the strings have the same exact characters (“xyz”), The code above will actually output:
obj1==obj2 is FALSE
Java String class actually overrides the default equals() implementation in the Object class – and it overrides the method so that it checks only the values of the strings, not their locations in memory. This means that if you call the equals() method to compare 2 String objects, then as long as the actual sequence of characters is equal, both objects are considered equal.
String obj1 = new String("xyz");
String obj2 = new String("xyz");
if(obj1.equals(obj2))
System.out.printlln("obj1==obj2 is TRUE");
else
System.out.println("obj1==obj2 is FALSE");
This code will output the following:
obj1==obj2 is TRUE
public static void main(String[] args){
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2));
////
System.out.println(s1 == s2);
System.out.println("-----------------------------");
String s3 = "hello";
String s4 = "hello";
System.out.println(s3.equals(s4));
////
System.out.println(s3 == s4);
}
Here in this code u can campare the both '==' and '.equals'
here .equals is used to compare the reference objects and '==' is used to compare state of objects..
The equals( ) method and the == operator perform two different operations. The equals( ) method compares the characters inside a String object. The == operator compares two object references to see whether they refer to the same instance. The following program shows how two different String objects can contain the same characters, but references to these objects will not compare as equal:
// equals() vs ==
class EqualsNotEqualTo {
public static void main(String args[]) {
String s1 = "Hello";
String s2 = new String(s1);
System.out.println(s1 + " equals " + s2 + " -> " +
s1.equals(s2));
System.out.println(s1 + " == " + s2 + " -> " + (s1 == s2));
}
}
The variable s1 refers to the String instance created by “Hello”. The object referred to by
s2 is created with s1 as an initializer. Thus, the contents of the two String objects are identical,
but they are distinct objects. This means that s1 and s2 do not refer to the same objects and
are, therefore, not ==, as is shown here by the output of the preceding example:
Hello equals Hello -> true
Hello == Hello -> false
Lets say that "==" operator returns true if both both operands belong to same object but when it will return true as we can't assign a single object multiple values
public static void main(String [] args){
String s1 = "Hello";
String s1 = "Hello"; // This is not possible to assign multiple values to single object
if(s1 == s1){
// Now this retruns true
}
}
Now when this happens practically speaking, If its not happen then why this is == compares functionality....
(1) == can be be applied for both primitives and object types, but equals() method can be applied for only object types.
(2) == cannot be overridden for content comparison, but equals method can be overridden for content comparison(ex; String class, wrapper classes, collection classes).
(3) == gives incomparable types error when try to apply for heterogeneous types , where as equals method returns false.
Here is a simple interpretation about your problem:
== (equal to) used to evaluate arithmetic expression
where as
equals() method used to compare string
Therefore, it its better to use == for numeric operations & equals() method for String related operations. So, for comparison of objects the equals() method would be right choice.