What Makes Reference Comparison (==) Work for Some Strings in Java

What makes reference comparison (==) work for some strings in Java?

The string constant pool will essentially cache all string literals so they're the same object underneath, which is why you see the output you do for s1==s2. It's essentially an optimisation in the VM to avoid creating a new string object each time a literal is declared, which could get very expensive very quickly! With your str1==str2 example, you're explicitly telling the VM to create new string objects, hence why it's false.

As an aside, calling the intern() method on any string will add it to the constant pool, so long as an equivalent string isn't there already (and return the String that it's added to the pool.) It's not necessarily a good idea to do this however unless you're sure you're dealing with strings that will definitely be used as constants, otherwise you may end up creating hard to track down memory leaks.

If == compares references in Java, why does it evaluate to true with these Strings?

The program will print Equal. (At least using the Sun Hotspot and suns Javac.) Here it is demonstrated on http://ideone.com/8UrRrk

This is due to the fact that string-literal constants are stored in a string pool and string references may be reused.

Further reading:

  • What is String literal pool?
  • String interning

This however:

public class Salmon {
public static void main(String[] args) {

String str1 = "Str1";
String str2 = new String("Str1");

if (str1 == str2) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
}
}

Will print Not equal since new is guaranteed to introduce a fresh reference.

So, rule of thumb: Always compare strings using the equals method.

How do I compare strings in Java?

== tests for reference equality (whether they are the same object).

.equals() tests for value equality (whether they contain the same data).

Objects.equals() checks for null before calling .equals() so you don't have to (available as of JDK7, also available in Guava).

Consequently, if you want to test whether two strings have the same value you will probably want to use Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true

// ... but they are not the same object
new String("test") == "test" // --> false

// ... neither are these
new String("test") == new String("test") // --> false

// ... but these are because literals are interned by
// the compiler and thus refer to the same object
"test" == "test" // --> true

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

You almost always want to use Objects.equals(). In the rare situation where you know you're dealing with interned strings, you can use ==.

From JLS 3.10.5. String Literals:

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 (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

Similar examples can also be found in JLS 3.10.5-1.

Other Methods To Consider

String.equalsIgnoreCase() value equality that ignores case. Beware, however, that this method can have unexpected results in various locale-related cases, see this question.

String.contentEquals() compares the content of the String with the content of any CharSequence (available since Java 1.5). Saves you from having to turn your StringBuffer, etc into a String before doing the equality comparison, but leaves the null checking to you.

Comparing string references

In

String s = "e!";
String str7 = "Lov"+ s;

While "e!" is a constant expression, s is not a constant variable (JLS §4.12.4); therefore, "Lov" + s, which references s, cannot be a constant expression (JLS §15.28). In order for a variable like s to be a constant variable, it needs to be both final and initialized from a constant expression.

If you had written

final String s = "e!";
String str7 = "Lov" + s;

then str1 == str7 would have been true.

Why DOES == sometimes work on Strings in Java?

Because string literals are intern'd, identical literals refer to the same object. Therefore, checking for reference equality between them will necessarily return true.

From the Java Language Specification (3.10.5):

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 (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

In practice, the compiler will pool the string literals "early" and store only one copy in the compiled .class file. However, identical string literals from separate class files will still compare equal using == since the literals are still intern'd when the classes are loaded.

If, on the other hand, we properly apply your example with Circle to String, we would have:

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // will print false!

In this case we explicitly create new objects, so they cannot be equal references.

Any string constructed by means other than a literal or other constant string expression will also not necessarily compare reference-equal with an identical string. For example:

String a = "hello";
String b = "hello";
System.out.println(a.substring(0,3) == b.substring(0,3)); // may print false!

String.equals versus ==

Use the string.equals(Object other) function to compare strings, not the == operator.

The function checks the actual contents of the string, the == operator checks whether the references to the objects are equal. Note that string constants are usually "interned" such that two constants with the same value can actually be compared with ==, but it's better not to rely on that.

if (usuario.equals(datos[0])) {
...
}

NB: the compare is done on 'usuario' because that's guaranteed non-null in your code, although you should still check that you've actually got some tokens in the datos array otherwise you'll get an array-out-of-bounds exception.

can some one help me if am checking the reference of the string then what would be the exact answer and why?

Equality operator checks whether the object references compared refer to the same object or literal.

Now, Java VM uses a pool for string literals and uses it for comparisons between literals. Because of that, direct operations on literals such as plus will lead to string literals and any instance of them refers to the same literal, in a sense, as the compiler reasons it is about the same literal:

"foo" + "bar" == "foobar" // true

However, if you apply operations that generate new String objects as a result (such as String.concat) then this leads to different String objects:

"foo".concat("bar") == "foobar" //false, object implicit comparison with literal

What is suggested is that if you want to compare two Strings in values, then use String.equals method:

"foo".concat("bar").equals("foobar") //true

How does the comparison in Strings work?

trim() returns a copy of this string with leading and trailing white space removed, or this string if it has no leading or trailing white space.

  • in the first case the answer is true no surprise about that because the references are equal

  • in the second case there are no leading or trailing spaces so trim returns the same string again the references are equal

  • in the last case trim returns a copy as the string has a trailing white space which results in a different reference so your comparison will be false.

Strings in Java : equals vs ==

First of all String.toString is a no-op:

/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
}

Second of all, String constants are interned so s1 and s2 are behind the scenes changed to be the same String instance.

Referential vs Structural equality in Kotlin in case of strings

So as far as string comparison goes, I think it does the same thing as java in that it adds everything to the string constant pool.

Here is the thread for referential string comparison in java (done by ==) -
What makes reference comparison (==) work for some strings in Java?

For Val vs Var the answer by @Tenfour04 below explains the logic.



Related Topics



Leave a reply



Submit