user3258303
user3258303

Reputation: 11

regarding String Constant Pool

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

Answers (3)

Stephen C
Stephen C

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

Lars Gendner
Lars Gendner

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

light_303
light_303

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

Related Questions