How do I compare strings in Java?
I've been using the
== operator in my program to compare all my strings so far.
However, I ran into a bug, changed one of them into
.equals() instead, and it fixed the bug.
== bad? When should it and should it not be used? What's the difference?
== tests for reference equality (whether they are the same object).
.equals() tests for value equality (whether they are logically "equal").
Consequently, if you want to test whether two strings have the same value you will probably want to use
// 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
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
Similar examples can also be found in JLS 3.10.5-1.
Other Methods To Consider
String.equalsIgnoreCase() value equality that ignores case.
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.
== tests object references,
.equals() tests the string values.
Sometimes it looks as if
== compares values, because Java does some behind-the-scenes stuff to make sure identical in-line strings are actually the same object.
String fooString1 = new String("foo"); String fooString2 = new String("foo"); // Evaluates to false fooString1 == fooString2; // Evaluates to true fooString1.equals(fooString2); // Evaluates to true, because Java uses the same object "bar" == "bar";
But beware of nulls!
null strings fine, but calling
.equals() from a null string will cause an exception:
String nullString1 = null; String nullString2 = null; // Evaluates to true System.out.print(nullString1 == nullString2); // Throws a NullPointerException System.out.print(nullString1.equals(nullString2));
So if you know that
fooString1 may be null, tell the reader that by writing
System.out.print(fooString1 != null && fooString1.equals("bar"));
The following are shorter, but it’s less obvious that it checks for null:
System.out.print("bar".equals(fooString1)); // "bar" is never null System.out.print(Objects.equals(fooString1, "bar")); // Java 7 required
Read more... Read less...
== compares Object references.
.equals() compares String values.
== gives illusions of comparing String values, as in following cases:
String a="Test"; String b="Test"; if(a==b) ===> true
This is because when you create any String literal, the JVM first searches for that literal in the String pool, and if it finds a match, that same reference will be given to the new String. Because of this, we get:
(a==b) ===> true
String Pool b -----------------> "test" <-----------------a
== fails in the following case:
String a="test"; String b=new String("test"); if (a==b) ===> false
In this case for
new String("test") the statement new String will be created on the heap, and that reference will be given to
b will be given a reference on the heap, not in String pool.
a is pointing to a String in the String pool while
b is pointing to a String on the heap. Because of that we get:
if(a==b) ===> false.
String Pool "test" <-------------------- a Heap "test" <-------------------- b
.equals() always compares a value of String so it gives true in both cases:
String a="Test"; String b="Test"; if(a.equals(b)) ===> true String a="test"; String b=new String("test"); if(a.equals(b)) ===> true
.equals() is always better.
== operator checks to see if the two strings are exactly the same object.
.equals() method will check if the two strings have the same value.
Strings in Java are immutable. That means whenever you try to change/modify the string you get a new instance. You cannot change the original string. This has been done so that these string instances can be cached. A typical program contains a lot of string references and caching these instances can decrease the memory footprint and increase the performance of the program.
When using == operator for string comparison you are not comparing the contents of the string, but are actually comparing the memory address. If they are both equal it will return true and false otherwise. Whereas equals in string compares the string contents.
So the question is if all the strings are cached in the system, how come
== returns false whereas equals return true? Well, this is possible. If you make a new string like
String str = new String("Testing") you end up creating a new string in the cache even if the cache already contains a string having the same content. In short
"MyString" == new String("MyString") will always return false.
Java also talks about the function intern() that can be used on a string to make it part of the cache so
"MyString" == new String("MyString").intern() will return true.
Note: == operator is much faster than equals just because you are comparing two memory addresses, but you need to be sure that the code isn't creating new String instances in the code. Otherwise you will encounter bugs.
String a = new String("foo"); String b = new String("foo"); System.out.println(a == b); // prints false System.out.println(a.equals(b)); // prints true
Make sure you understand why. It's because the
== comparison only compares references; the
equals() method does a character-by-character comparison of the contents.
When you call new for
b, each one gets a new reference that points to the
"foo" in the string table. The references are different, but the content is the same.
Yea, it's bad...
== means that your two string references are exactly the same object. You may have heard that this is the case because Java keeps sort of a literal table (which it does), but that is not always the case. Some strings are loaded in different ways, constructed from other strings, etc., so you must never assume that two identical strings are stored in the same location.
Equals does the real comparison for you.