Let's assume you are right and see what's going to happen when we call equalsIgnoreCase(null):
this == anotherStringis false;anotherString.value.length == value.length- We are getting a NPE onanotherString.value.
Therefore, anotherString != null is necessary and crucial here.
this != anotherStringalready indicates thatanotherStringis notnull.
No, it doesn't. It can only state whether this and anotherString not equal.
For instance, both this != null and this != "test" return true.
Let's assume you are right and see what's going to happen when we call equalsIgnoreCase(null):
this == anotherStringis false;anotherString.value.length == value.length- We are getting a NPE onanotherString.value.
Therefore, anotherString != null is necessary and crucial here.
this != anotherStringalready indicates thatanotherStringis notnull.
No, it doesn't. It can only state whether this and anotherString not equal.
For instance, both this != null and this != "test" return true.
Of course it's necessary.
this != anotherString may imply anotherString is a different String or anotherString is null
string == null compares if the object is null. string.equals("foo") compares the value inside of that object. string == "foo" doesn't always work, because you're trying to see if the objects are the same, not the values they represent.
Longer answer:
If you try this, it won't work, as you've found:
String foo = null;
if (foo.equals(null)) {
// That fails every time.
}
The reason is that foo is null, so it doesn't know what .equals is; there's no object there for .equals to be called from.
What you probably wanted was:
String foo = null;
if (foo == null) {
// That will work.
}
The typical way to guard yourself against a null when dealing with Strings is:
String foo = null;
String bar = "Some string";
...
if (foo != null && foo.equals(bar)) {
// Do something here.
}
That way, if foo was null, it doesn't evaluate the second half of the conditional, and things are all right.
The easy way, if you're using a String literal (instead of a variable), is:
String foo = null;
...
if ("some String".equals(foo)) {
// Do something here.
}
If you want to work around that, Apache Commons has a class - StringUtils - that provides null-safe String operations.
if (StringUtils.equals(foo, bar)) {
// Do something here.
}
Another response was joking, and said you should do this:
boolean isNull = false;
try {
stringname.equalsIgnoreCase(null);
} catch (NullPointerException npe) {
isNull = true;
}
Please don't do that. You should only throw exceptions for errors that are exceptional; if you're expecting a null, you should check for it ahead of time, and not let it throw the exception.
In my head, there are two reasons for this. First, exceptions are slow; checking against null is fast, but when the JVM throws an exception, it takes a lot of time. Second, the code is much easier to read and maintain if you just check for the null pointer ahead of time.
s == null
won't work?
Since Java 7 you can use the static method java.util.Objects.equals(Object, Object) to perform equals checks on two objects without caring about them being null.
If both objects are null, it will return true, if one is null and the other isn't, it will return false. Otherwise, it will return the result of calling equals on the first object with the second as argument.
This is what Java internal code uses (on other compare methods):
public static boolean compare(String str1, String str2) {
return (str1 == null ? str2 == null : str1.equals(str2));
}
If you are not only limited to JDK you can use
StringUtils.equalsIgnoreCase(CharSequence str1, CharSequence str2)
from apache-commons lang which is null-safe and will return
StringUtils.equalsIgnoreCase(null, null) = true
StringUtils.equalsIgnoreCase(null, "abc") = false
StringUtils.equalsIgnoreCase("abc", null) = false
StringUtils.equalsIgnoreCase("abc", "abc") = true
StringUtils.equalsIgnoreCase("abc", "ABC") = true
The method String.equalsIgnoreCase(String) is "unfortunately" a little more complex. You can look into the code, but it is well explained in the javadoc itself:
Compares this String to another String, ignoring case considerations. Two strings are considered equal ignoring case if they are of the same length and corresponding characters in the two strings are equal ignoring case.
Two characters c1 and c2 are considered the same ignoring case if at least one of the following is true:
- The two characters are the same (as compared by the == operator)
- Applying the method Character.toUpperCase(char) to each character produces the same result
- Applying the method Character.toLowerCase(char) to each character produces the same result