Comparing two equal Strings after intern() method [duplicate] - java

This question already has answers here:
How do I compare strings in Java?
(23 answers)
String comparison confused
(3 answers)
Closed 6 years ago.
Javadoc says that if in the string pool there is an equal String that the intern() method will return the String.
public class Demo {
public static void main(String[] args) {
String str1 = "Apple";
String str2 = new String("Apple");
System.out.println(str1.intern() == str2); //false
System.out.println(str1 == str2.intern()); //true
}
}
I expected to get true in both cases.

System.out.println(str1.intern() == str2); //false
In the above case you are comparing reference of interned String "Apple" with that of reference of another String which is on the heap (but with the same value). So, the result is "false".
System.out.println(str1 == str2.intern()); //true
In the above case, you are comparing a reference of String constants pool to a reference got by trying to add "Apple" to the String constants pool. SInce, "Apple" is already in the first line, this interning will return the object pointed to by str1. Hence you get true.
PS : This behavior is described in the javadoc

Doing this str1.intern() is bringing nothing to your try...
Since str1 is a literal string (it will be inmediatly placed in the string pool), and you are comparing it against the str2 which is allocated on the Heap...
therefore
System.out.println(str1.intern() == str2);
will print false, you are comparing the reference of a string in the stirng pool vs a string on the heap...

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
System.out.println(firstString.intern() == secondString);//false because it will fetch exact copy of the string compare in string
System.out.println(firstString == secondString.intern());//True because it will compare firstString with fetch the second String it will check heap or not

Related

the method StringBuilder.append() , has changed the result of String.intern() [duplicate]

This question already has answers here:
The return of String.intern() explained
(3 answers)
Java String intern function result problem [duplicate]
(1 answer)
String builder not using string literal from string pool. Why?
(4 answers)
Closed 1 year ago.
String s1 = new StringBuilder("dsada").append("dfgdfgd").toString();
String s3 = new StringBuilder("aaaa").toString();
System.out.println(s1.intern() == s1); //true
System.out.println(s3.intern() == s3); //false
the s1 and s3 finally invoke StringBuilder.toString,
the method toString() contrust a new String(),and then invoke the String.intern(),the result is different,it confused me a lot.
#Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
From https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#intern():
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.
"aaaa" is a string literal in your code, so it's already in the interned pool. When you call intern() on a string with value "aaaa", it returns the existing string object that it retrieved from the pool. That's not the same object as s3.
"dsadadfgdfgd" is not a string literal in your code, so when you call intern(), it adds that string object to the pool, and then returns it, the same object.

Using "==" in Java [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
What is the difference between "text" and new String("text")?
(13 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args)
{
String s1 = "HELLO";
String s2 = "HELLO";
System.out.println(s1 == s2); // true
}
}
But when I use :
public class Test {
public static void main(String[] args)
{
String s1 = new String("HELLO");
String s2 = new String("HELLO");
System.out.println(s1 == s2); // false
}
}
Can anybody please explain the difference here? Thankyou!
In the first example
String s1 = "HELLO";
String s2 = "HELLO";
the values of s1 and s2 are compile-time constants. Thus, the compiler does only generate a single String-object, holding the value "HELLO" and assings it to both s1 and s2. This is a special case of Common Subexpression Elimination, a well-known compiler optimization. Thus s1 == s2 returns true.
In the second example, two different Strings are constructed explicitly through new. Thus, they have to be separate objects per the semantics of new.
I created an Ideone demo a while back that highlights some cases that show this behaviour.
You can enforce that the same String is return by using String::intern():
String s1 = new String("HELLO").intern();
String s2 = new String("HELLO").intern();
System.out.println(s1 == s2); // will print "true";
Ideone demo
In case of String literal,before creating new Object in String Constant Pool ,JVM will check already same Object persist in SCP area or not if yes it will point to same object instead of creating new Object.Hence, below code s1 == s2 is true
String s1 = "HELLO";
String s2 = "HELLO";
System.out.println(s1 == s2); // true
but we are creating new object by using new keyword, it will create object in heap area, hence s1 and s2 are pointing to two different object, hence it is return false
== tests for reference equality (whether they are the same object).
.equals() tests for value equality (whether they are logically "equal").
from here How do I compare strings in Java?
== compares the objects reference pointer. When 2 objects are same exact object it will be true.
Instantiating a string using double quotes uses the string pool, creates a string once and reuses it.
Instantiating a string wit new always creates a brand new string.
== tests for reference equality (whether they are the same object).
First Case
System.out.println(s1 == s2); // true
Because you are comparing literals that are interned by the compiler and thus refer to the same object. Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions - are "interned" so as to share unique instances, using the method String.intern.
Second Case
System.out.println(s1 == s2); // false
You are comparing the Object reference which is different so you are getting false.
Please check https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28
i first case u comparing two strings with its ASCII values. thats why...//true
and in second case you are comparing two functions/methods. thats why... //false
the first one is true because s1 and s2 refer to the same string literal in the method area, the memory references are the same. ( == checks just the references in string). when the same string literal is created more than once, only one copy of each distinct string value is stored.
the second one is false because s1 and s2 refer to two different objects in the heap. different objects always have different memory references.

Java String intern function result problem [duplicate]

This question already has answers here:
The return of String.intern() explained
(3 answers)
Closed 3 years ago.
I'm learning Java now, and i read this question:What is Java String interning? - Stack Overflow
but i read other articles which provide some examples i don't understand:
public static void main(String[] args) {
String str2 = new String("str") + new String("01");
str2.intern();
String str1 = "str01";
System.out.println(str2 == str1); //true
String s4 = new String("1");
s4.intern();
String s5 = "1";
System.out.println(s4 == s5); //false
String s = new StringBuilder("aa").append("bb").toString();
String s2 = new StringBuilder("cc").toString();
System.out.println(s.intern() == s); //true
System.out.println(s2.intern() == s2); //false
}
the result in Java 11( it should be same in Java 8) is :
true
false
true
false
i don't know why results are different, i suppose it to be all true.
can anyone explains it?
Let's look at what intern actually does (emphasis mine):
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.
When this code is run:
str2.intern();
The string pool only contains "str" and "01". str2 is "str01", which is not in the string pool, so the object that str2 refers too is added to the string pool. Therefore, when the next line is reached, since "str01" is already in the pool, str1 will refer to the same object as str2.
Note that the reason why str2 == str1 is not because intern somehow changes which object str2 refers to. It doesn't do anything to str2. Strings are immutable after all.
Now we can understand the first false. In the line:
String s4 = new String("1");
Because of the string literal "1", "1" is added to the string pool. Note that the object that is added to the string pool is not the same as the object to which s4 refers. Now you call s4.intern(), which does nothing to s4, and returns the object that is in the string pool. But you are ignoring the return value. This is why s4 != s5, and s4.intern() == s5.
The reason for s2.intern() != s2 is much simpler - s2 refers to a different object than "cc" in the string pool! s2.intern() is supposed to return the object in the string pool, so of course it is not the same object!

Java String Objects [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I have the following code:
public class Porow{
public static void main (String[] args){
String s1 = "foo";
String s2 = "foo";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
String s3 = new String ("foo");
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));
}
}
which outputs:
true
true
false
true
I am trying to understand and explain what's going on here. And I need some guidance. Will I be right to say s1 and s2 are same objects stored in different parts of memory and that's why we get the first 2 trues?
Why is the 3rd output false? is s3 a different object? and why does it produce true with the equals method on s1? I'd appreciate some help. Thanks :).
EDIT:
This question is not about == nor equals() I know what they are. My question is more related to memory references and addresses. So don't just presume I'm asking about String Comparison. I'm asking about a whole different thing here.
That's because in the 3rd scenario, a new object is created(the new keyword creates a new string object) and == is used for object reference equality. That's why it returns false.
Whereas the equals() method is used for String value equality, and hence, it returns true.
In the first and second case, the "foo" String literal is interned and thus, both s1 and s2 refer the same String literal.
The == operator checks reference equivalence. If the two references are equivalent, then they're the same instance.
Your first example works because the strings are interned - but don't rely on this. equals() actually checks to see if the two Strings contain the same data.
With the new keyword, a new reference is created for the other string - hence, they no longer point to the same instance.
Because == tests that the strings refer to the same object and equals tests if they are equivalent. Your line
String s3 = new String ("foo");
constructs a new reference to the constant "foo" String. Take a look at What is String interning? for a bit more, but be aware that interning will use PermGen space.
String are put into a String pool
When you have
String s1 = "foo";
String s2 = "foo";
Only one "foo" is placed into the String pool.
So
s1 == s2 is true becuase they reference the Same String "foo" in the pool
To answer your question, your assumptions are right!
The last true s1.equals(s3) compares the value "foo", that's why they are equal.
So just remember with Strings
== compares Object reference
equals compares value.

Understanding how string comparison works in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I compare strings in Java?
I am new to Java and I have difficulties in understanding String comparison. Can anyone explain the differences between the following scenarios?
Scenario 1 :
String a = "abc";
String b = "abc";
When I run the if(a == b) it returns true.
Scenario 2 :
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
What is the difference?
== operator compares the references of two objects in memory. If they point to the same location then it returns true.String object in java are Immutable, so when you create Strings like in scenario1 then it didn't create new string. It just points the second string to the memory location of first string.
However, .equals() method compares the content of the String. When strings has same value then this method returns true.
So, in general it is recommended to use equals() method instead of ==.
It's because of Java String constant memory pool. Same valued literals are stored once.
String a = "abc";
String b = "abc";
// Now there is 1 string ("abc") and 2 references pointing to it.
String a = new String("abc");
String b = new String("abc");
// Now you have 2 string instances and 2 references.
Scenario 1 returns true because of a compiler optimization.
In general you should use equals() instead of == to compare strings.
In Java you need to use like this if(str.equals(str2)) which compares actual value of string rather than references.
Case1:
String a = "abc";
String b = "abc";
if(a == b)
In this case abc is cached in String constant pool thus a new string is not created String b = "abc"; b just refers to the string created by a it returns true as a and b both point to the same Object in the memory.
Case2:
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
Here a two Strings are created and == operator just checks if two references point to the same reference, which it doesnt in this case thus it returns false
Two ways of creating string are
1) String s ="hello"; No. of string literal = 1 i.e. "hello" - No. of String objects on heap = 0
2) String s= new String("hello"); - No. of string literals =1 and No. of string objects =1
Java maintains a string pool of "LITERALS" and objects are going to stay on heap.
Advantage of string pooling: 1) Reduced memory usage*(PermGenSpace Issue) 2) Faster Comparision i.e == comparision 3) Faster lookup
Disadvantages: 1) Overhead of maintaining pool
How to pool String objects? Use Intern() on a string to add it to the pool. Downside of interning: 1) You may forget to intern some strings and compare them by == leading to unexpected results.
The reason is that the String literal "abc" will be turned into a global String instance for all its ocurrences, it will be the same String instance therefore you can be sure that "abc" == "abc". It is possible for the compiler to do that because String instances are immutable. However, if you explicitly allocate the String they will be two different instances and they will also be different to the String instance implicitly created by the compiler i.e. new String("abc") != new String("abc") and "abc" != new String("abc").
Another good example to understand what the compiler is doing is to look at this code:
"abc".contains("a");
you see that the literal behaves like an instance of a String type. You may exploit this to minimize programming errors e.g.
// this is OK and the condition will evaluate to false
String myStringValue = null;
if ("abc".equals(myStringValue)) { // false
whereas this code results in NPE:
// this will produce a NPE
String myStringValue = null;
if (myStringValue.equals("abc")) { // NPE

Categories