Reputation: 11
Assume that I have 2 Strings a="ABC"
and b="ABC"
and I believe there will be only one string will be created and both these string references will point to the instance in the String Constant Pool. In this case, why do we need .equals()
method to compare. Please clarify.
Upvotes: 0
Views: 84
Reputation: 718758
I believe there will be only one string will be created and both these string references will point to the instance in the String Constant Pool.
Close. The "constant pool" actually refers to a section in the classfile representation, and it contains other things than strings.
The place where your "ABC" string object is held at runtime doesn't have a name according to the Java specs. The Javadoc just refers to it as "a string pool", and the JLS doesn't explicitly mention it at all. Also, this pool may also contain strings that have been created by application code calling String::intern
at runtime.
Why do we need .equals() method to compare?
Because most string objects are NOT created by calling String::intern
.
Only string objects that have been interned by the class loader (because they represent literals in the source code) or by application code calling String::intern
will be in the pool.
If you don't know (for sure) that the two strings you are comparing have been interned, then you cannot be sure that ==
will give the correct answer. Hence, the safe way to test if two strings are equal is to use String::equals
.
(Footnote: The G1 garbage collector can also do something known as "string deduplication" (see JEP 192) but this is a different process to interning and does not alter the identity of the string objects. It is therefore not relevant to this question.)
Upvotes: 1
Reputation: 1982
From the JDK8 implementation of java.lang.String#equals()
:
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Note that the implementation first checks this
and anObject
for identity. And this is the correct place for such an implementation-dependent optimization. Your code should not rely on such assumptions, since String#equals()
does this for you.
Upvotes: 0
Reputation: 2111
This is basically the same for all kinds of pools or caches with limited capacity - can can not assume that the content of the pool is constant and never changing.
There are potentially a ton of other strings being created everywhere and the pool might evict items at will when hitting capacity.
Also other components might still create new Strings (new String(byte[])) with the exact same content, that you have no control over and might end up comparing.
Upvotes: 0