You cannot use the dereference (dot, '.') operator to access instance variables or call methods on an instance if that instance is null. Doing so will yield a NullPointerException.
It is common practice to use something you know to be non-null for string comparison. For example, "something".equals(stringThatMayBeNull).
You cannot use the dereference (dot, '.') operator to access instance variables or call methods on an instance if that instance is null. Doing so will yield a NullPointerException.
It is common practice to use something you know to be non-null for string comparison. For example, "something".equals(stringThatMayBeNull).
Use Objects.equals() to compare strings, or any other objects if you're using JDK 7 or later. It will handle nulls without throwing exceptions. See more here: how-do-i-compare-strings-in-java
And if you're not running JDK 7 or later you can copy the equals method from Objects like this:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
When I type
string1 == string2
IntelliJ tells me to switch to equals(), which it says is null-safe.
But is == operator not null-safe?
I tried null == "abc", "abc" == null, null == null, but they consistently gave me right false false true.
What am I missing here?
Videos
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 (myString != null && !myString.isEmpty()) {
// doSomething
}
As further comment, you should be aware of this term in the equals contract:
From Object.equals(Object):
For any non-null reference value
x,x.equals(null)shouldreturn false.
The way to compare with null is to use x == null and x != null.
Moreover, x.field and x.method() throws NullPointerException if x == null.
If myString is null, then calling myString.equals(null) or myString.equals("") will fail with a NullPointerException. You cannot call any instance methods on a null variable.
Check for null first like this:
if (myString != null && !myString.equals("")) {
//do something
}
This makes use of short-circuit evaluation to not attempt the .equals if myString fails the null check.
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:
CopyString 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:
CopyString foo = null;
if (foo == null) {
// That will work.
}
The typical way to guard yourself against a null when dealing with Strings is:
CopyString 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:
CopyString 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.
Copyif (StringUtils.equals(foo, bar)) {
// Do something here.
}
Another response was joking, and said you should do this:
Copyboolean 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.
Copys == null
won't work?
If Java 7+, use Objects.equals(); its documentation explicitly specifies that:
[...] if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
which is what you want.
If you don't, your method can be rewritten to:
Copyreturn s1 == null ? s2 == null : s1.equals(s2);
This works because the .equals() contract guarantees that for any object o, o.equals(null) is always false.
From Objects.equals():
Copyreturn (a == b) || (a != null && a.equals(b));
Very simple, self-explaining and elegant.
Using "abc".equals(...) is a reasonable precaution against a condition you didn't anticipate, but doesn't really solve any problems. Maybe this particular method doesn't care that myString is null (the string comparison returns false, but that's it), but what about elsewhere? Now there's this null value working its way through your logic that's not supposed to be there.
In this particular case, it might not matter, but in another, letting this invalid value pass through part of the logic could lead to an incorrect state later on (e.g. an address with the city missing). Fail early!
If myString should not be null, then write the code so that it can't be. Add contracts to your methods, or at least some in-method argument validation to ensure invalid values are dealt with before the method's logic ever executes. Then be sure your tests cover these cases.
One goal of programming is robust code, ie. code that doesn't die horribly whenever something unexpected crops up.
in case of if ("abc".equals(myString)), the if clause doesn't get executed if the string is null, so throwing an exception isn't necessary. Of course it could be caused by bugs in code, but those should be found during developing/testing, not in production, by the customer!
Actually, i would take "abc".equals(myString) as an indication that the programmer explicitly didn't care whether the string was null or not. In critical code, i'd expect a lot more explicit checking.
1st one is better (and the only option), because 2nd one will throw NPE, when your value is actually null. As simple as that.
Try this out:
String str = null;
str.equals(null); // will throw `NPE`.
So basically, the test which you wanted to perform itself triggers a NullPointerException in the 2nd case. So, it is no choice.
!str.equals(null) will
- always return false if it does not throw an exception, and
- throw an exception if str is null
The point of a null check is to make sure the reference, in this code str, actually refers to an object. If it is null, you can't call any methods on it, including equals, without throwing a NullPointerException... which the point of null checks is to avoid happening.
So !str.equals(null) causes the very problem null checks are meant to prevent and doesn't do what you think at all. Never do this.