The contract of equals with regards to null, is as follows:
For any non-null reference value x, x.equals(null) should return false.
This is rather peculiar, because if o1 != null and o2 == null, then we have:
o1.equals(o2) // returns false
o2.equals(o1) // throws NullPointerException
The fact that o2.equals(o1) throws NullPointerException is a good thing, because it alerts us of programmer error. And yet, that error would not be catched if for various reasons we just switched it around to o1.equals(o2), which would just "silently fail" instead.
So the questions are:
Why is it a good idea that o1.equals(o2) should return false instead of throwing NullPointerException?
Would it be a bad idea if wherever possible we rewrite the contract so that anyObject.equals(null) always throw NullPointerException instead?
On comparison with Comparable
In contrast, this is what the Comparable contract says:
Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
If NullPointerException is appropriate for compareTo, why isn't it for equals?
Related questions
Comparable and Comparator contract with regards to null
A purely semantical argument
These are the actual words in the Object.equals(Object obj) documentation:
Indicates whether some other object is "equal to" this one.
And what is an object?
JLS 4.3.1 Objects
An object is a class instance or an array.
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.
My argument from this angle is really simple.
equals tests whether some other object is "equal to" this
null reference gives no other object for the test
Therefore, equals(null) should throw NullPointerException
To the question of whether this asymmetry is inconsistent, I think not, and I refer you to this ancient Zen kōan:
Ask any man if he's as good as the next man and each will say yes.
Ask any man if he's as good as nobody and each will say no.
Ask nobody if it's as good as any man and you'll never get a reply.
At that moment, the compiler reached enlightenment.
An exception really should be an exceptional situation. A null pointer might not be a programmer error.
You quoted the existing contract. If you decide to go against convention, after all this time, when every Java developer expects equals to return false, you'll be doing something unexpected and unwelcome that will make your class a pariah.
I could't disagree more. I would not rewrite equals to throw an exception all the time. I'd replace any class that did that if I were its client.
Think of how .equals is related to == and .compareTo is related to the comparison operators >, <, >=, <=.
If you're going to argue that using .equals to compare an object to null should throw a NPE, then you'd have to say that this code should throw one as well:
Object o1 = new Object();
Object o2 = null;
boolean b = (o1 == o2); // should throw NPE here!
The difference between o1.equals(o2) and o2.equals(o1) is that in the first case you're comparing something to null, similar to o1 == o2, while in the second case, the equals method is never actually executed so there's no comparison happening at all.
Regarding the .compareTo contract, comparing a non-null object with a null object is like trying do this:
int j = 0;
if(j > null) {
...
}
Obviously this won't compile. You can use auto-unboxing to make it compile, but you get a NPE when you do the comparison, which is consistent with the .compareTo contract:
Integer i = null;
int j = 0;
if(j > i) { // NPE
...
}
Not that this is neccessarily an answer to your question, it is just an example of when I find it useful that the behaviour is how it is now.
private static final String CONSTANT_STRING = "Some value";
String text = getText(); // Whatever getText() might be, possibly returning null.
As it stands I can do.
if (CONSTANT_STRING.equals(text)) {
// do something.
}
And I have no chance of getting a NullPointerException. If it were changed as you suggested, I would be back to having to do:
if (text != null && text.equals(CONSTANT_STRING)) {
// do something.
}
Is this a good enough reason for the behaviour to be as it is?? I don't know, but it is a useful side-effect.
If you take object oriented concepts into account, and consider the whole sender and receiver roles, I'd say that behaviour is convenient. See in the first case you're asking an object if he is equal to nobody. He SHOULD say "NO, I'm not".
In the second case though, you don't have a reference to anyone So you aren't really asking anyone. THIS should throw an exception, the first case shouldn't.
I think it's only asymmetric if you kind of forget about object orientation and treat the expression as a mathematical equality. However, in this paradigm both ends play different roles, so it is to be expected that order matters.
As one final point. A null pointer exception should be raised when there's an error in your code. However, Asking an object if he is nobody, shouldn't be considered a programming flaw. I think it's perfectly ok to ask an object if he isn't null. What if you don't control the source that provides you with the object? and this source sends you null. Would you check if the object is null and only afterwards see if they are equals? Wouldn't it be more intuitive to just compare the two and whatever the second object is the comparison will be carried out without exceptions?
In all honesty, I would be pissed if an equals method within its body returns a null pointer exception on purpose. Equals is meant to be used against any sort of object, so it shouldn't be so picky on what it receives. If an equals method returned npe, the last thing on my mind would be that it did that on purpose. Specially considering it's an unchecked exception. IF you did raise an npe a guy would have to remember to always check for null before calling your method, or even worse, surround the call to equals in a try/catch block (God I hate try/catch blocks) But oh well...
Personally, I'd rather it perform as it does.
The NullPointerException identifies that the problem is in the object against which the equals operation is being performed.
If the NullPointerException was used as you suggest and you tried the (sort of pointless) operation of...
o1.equals(o1) where o1= null...
Is the NullPointerException thrown because your comparison function is screwed or because o1 is null but you didn't realise?
An extreme example, I know, but with current behaviour I feel you can tell easily where the problem lies.
In the first case o1.equals(o2) returns false because o1 is not equal to o2, which is perfectly fine. In the second case, it throws NullPointerException because o2 is null. One cannot call any method on a null. It may be a limitation of programming languages in general, but we have to live with it.
It is also not a good idea to throw NullPointerException you are violating the contract for the equals method and making things more complex than it has to be.
There are many common situations where null is not in any way exceptional, e.g. it may simply represent the (non-exceptional) case where a key has no value, or otherwise stand for “nothing”. Hence, doing x.equals(y) with an unknown y is also quite common, and having to always check for null first would be just wasted effort.
As for why null.equals(y) is different, it is a programming error to call any instance method on a null reference in Java, and therefore worthy of an exception. The ordering of x and y in x.equals(y) should be chosen such that x is known to not be null. I would argue that in almost all cases this reordering can be done based on what is known about the objects beforehand (e.g., from their origin, or by checking against null for other method calls).
Meanwhile if both objects are of unknown “nullness”, then other code almost certainly requires checking at least one of them, or not much can be done with the object without risking the NullPointerException.
And since this is the way it is specified, it is a programming error to break the contract and raise an exception for a null argument to equals. And if you consider the alternative of requiring an exception to be thrown, then every implementation of equals would have to make a special case of it, and every call to equals with any potentially null object would have to check before calling.
It could have been specified differently (i.e., the precondition of equals would require the argument to be non-null), so this is not to say that your argumentation is invalid, but the current specification makes for a simpler and more practical programming language.
Note that the contract is "for any non-null reference x". So the implementation will look like:
if (x != null) {
if (x.equals(null)) {
return false;
}
}
x need not be null to be deemed equal to null because the following definition of equals is possible:
public boolean equals(Object obj) {
// ...
// If someMember is 0 this object is considered as equal to null.
if (this.someMember == 0 and obj == null) {
return true;
}
return false;
}
I think it's about convenience and more importantly consistency - allowing nulls to be part of the comparison avoids having to do a null check and implement the semantics of that each time equals is called. null references are legal in many collection types, so it makes sense they can appear as the right side of the comparison.
Using instance methods for equality, comparison etc., necessarily makes the arrangement asymmetric - a little hassle for the huge gain of polymorphism. When I don't need polymorphism, I sometimes create a symmetric static method with two arguments, MyObject.equals(MyObjecta, MyObject b). This method then checks whether one or both arguments are null references. If I specifically want to exclude null references, then I create an additional method e.g. equalsStrict() or similar, that does a null check before delegating to the other method.
You should return false if the parameter is null.
To show that this is the standard, see 'Objects.equals(Object, Object) from java.util, that performs an assymetric null check on the first parameter only (on which equals(Object) will be called). From the OpenJDK SE 11 source code (SE 1.7 contains exactly the same):
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
This also handles two null values as equal.
This is a tricky question. For backward compatability you can't do so.
Imagine the following scenario
void m (Object o) {
if (one.equals (o)) {}
else if (two.equals (o)) {}
else {}
}
Now with equals returning false else clause will get executed, but not when throwing an exception.
Also null is not really equal to say "2" so it makes perfect sense to return false. Then it is probably better to insist null.equals("b") to return also false :))
But this requirement does make a strange and non symmetric equals relation.
Related
I have a graph related method which returns the neighboring nodes of a certain node.
If the one node has no neighbors it returns null, the method is the following
public Iterable<Node> getNeighbors(Node v) {
if (!this.adjacencyList.get(v).isEmpty())
return this.adjacencyList.get(v);
return null;
}
I try to avoid the exception using the following :
if (graph.getNeighbors(nodeIterator.name) == null)
nodeIterator = all_graph_nodes.iterator().next();
Iterable<Node> adjNodes = graph.getNeighbors(nodeIterator.name);
The NullPointerException is raised even using the previous code.
How to solve this ?
If you're still getting an NPE, then the problem is in getNeighbours and not the second snippet.
this.adjacencyList is null, -OR-
this.adjacencyList.get(v) returns null.
Given that you're passing a name to a method that will then do a lookup by node, and that you can't call .get(someNodeRef) on a list, adjacencyList is probably some sort of hashmap, so your names are off and you should rename some things. Map's .get(x) method returns null if an entry is not found, so most likely the culprit is that v isn't in the map at all, and thus .get(v).isEmpty() throws NPE.
The fixes are as follows:
You should NEVER return null when a valid sentinel value that carries the intended semantic meaning is available. A mouthful, but it means here: Why are you returning null when you intend to treat that the exact same way as 'zero nodes'? There is an instance of Iterable<Node> that properly represents the concept of zero nodes, and it isn't null. It's List.of() or equivalent: An empty list has no nodes. Great. That's what you intended. So return that.
.get(v).isEmpty() is bad code here, as it would mean an NPE occurs if you ask for a non-existent node. Unless, of course, you want it to work that way. An easy way out is the defaulting mechanism: Call .getOrDefault instead:
if (!this.adjacencyList.getOrDefault(v, List.of()).isEmpty()) ....
except, of course, you should never be returning null when you can return an empty list instead, so your getNeighbours method becomes simply:
return adjacencyMap.getOrDefault(v, List.of());
that one-liner will fix all things.
In general, if you are writing code where null is dealt with in some way, and some sentinel value (such as a blank string or an empty list) is dealt with in the same way, your code is badly styled; however you got that null should have gotten you that empty value instead. e.g. if you ever write this:
if (x == null || x.isEmpty()) ...
you messed up. Figure out where you got x from. Update it there, make x the blank sentinel ("" for strings, List.of for lists, etcetera).
That, and use .getOrDefault and other such methods more: Methods that let you provide what should happen when e.g. a key is not found.
You should probably avoid returning null from your getNeighbors method. It's not good practice to return null for Iterables, Iterators and Collections, since an empty iterable would represent the same concept (there is nothing in that adjacency list) without all the dangers of null. And your code would be simpler. You can check if the iterable contains anything and if not then default to the full iterator.
You should avoid returning null at all cost. This is of high danger as it may cause Null Pointer Exceptions to be thrown during runtime. Such exceptions are horrific to debug as they usually hide implementation errors due to the place where the exception was thrown is most likely far away from the original implementation error.
Your case is actually a good example of such behavior as it is not directly understandable where the NPE is coming from.
In situations in which the appearance of a null value is inevitable (e.g. as #rzwitserloot pointed out, Java's Map get method) and there is the possibility of exposing it to client objects (e.g. your getNeighbors method may expose such null value) I like to use Java's Optional which (as stated in the docs) is:
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
This object will act as wrapper to objects which may be assigned as null thus preventing it to be used directly and possibly preventing NPEs to be thrown.
In your case this would apply as follows (note that this is assuming that adjancencyList is a non-null object and that its get method is the one actually throwing the NPE):
public Optional<Iterable<Node>> getNeighbors(Node v) {
return Optional.ofNullable(this.adjacencyList.get(v));
}
if (!graph.getNeighbors(nodeIterator.name).isPresent()) {
nodeIterator = all_graph_nodes.iterator().next();
}
Iterable<Node> adjNodes = graph.getNeighbors(nodeIterator.name).get();
Note that by wrapping the original get method in an Optional object there is no longer the propagation of a raw null value hence preventing it to be used by the client. You are moving the responsibility of dealing with null to your side only and protecting clients to handle them instead.
Another great advantage of using Optional as a method's return type is that it implicitly declares that the return object of the method may or may not be present. This forces clients to understand that its return value may be empty (null) and thus force it to act accordingly.
Which one is recommended and to be used to check the Object null-ness?
null != Object
or
Object != null
and other way
null == Object
or
Object == null
...and is there any difference between them?
(In)equality is commutative, so there is no difference.
Historically the former stems from C to avoid accidentally assigning a value in a conditional statement, however that mostly applies to ==, not !=. Also Java requires the condition in a conditional statement to have a boolean value, so the only place where it could go wrong nowadays would be
if (a == false) ...
if you accidentally omit one of the =. A rare case, I guess (though probably not so much, given what students frequently write in their first two terms). Joonas also points out another (more obscure) case in the comments.
It's always more readable to use
Object != null
because that reads as "the object is not null", which is literally what the condition is.
The only case where you want to swap the two is to avoid accidentally using
Object = null
which will return true even though it is not the desired behavior, when you wanted to say
Object == null
but in reality not only do modern tools catch these kinds of mistakes, but wide use of the reverse can actually be an impediment to anyone who has to read the code.
Every method accepts a set of parameter values. Should we always validate the non-nullness of input parameters or allow the code to fail with classic RunTimeException?
I have seen a lot of code where people don't really check the nullness of input parameters and just write the business logic using the parameters. What is the best way?
void public( String a, Integer b, Object c)
{
if( a == null || b == null || c == null)
{
throw new RunTimeException("Message...");
}
.....business logic.....
}
The best way is to only check when necessary.
If your method is private, for example, so you know nobody else is using it, and you know you aren't passing in any nulls, then no point to check again.
If your method is public though, who knows what users of your API will try and do, so better check.
If in doubt, check.
If the best you can do, however, is throw a NullPointerException, then may not want to check. For example:
int getStringLength(String str) {
return str.length();
}
Even if you checked for null, a reasonable option would be throwing a NullPointerException, which str.length() will do for you anyways.
No. It's standard to assume that parameters will not be null and that a NullPointerException will be thrown otherwise. If your method allows a parameter to be null, you should state that in your api.
It's an unfortunate aspect of Java that references can be null and there is no way to specify in the language that they are not.
So generally yes, don't make up an interpretation for null and don't get into a situation where an NPE might be thrown later.
JSR305 (now inactive) allowed you to annotate parameters to state that they should not be given nulls.
void fn(#Nonnull String a, #Nonnull Integer b, #Nonnull Object c) {
Verbose, but that's Java for you. There are other annotation libraries and checkers that do much the same, but are non-standard.
(Note about capitalisation: When camel-casing words of the form "non-thing", the standard is not to capitalise the route word unless it is the name of a class. So nonthing and nonnull.)
Annotations also don't actually enforce the rule, other than when a checker is run. You can statically include a method to do the checking:
public static <T> T nonnull(T value) {
if (value == null) {
throwNPE();
}
return value;
}
private static void throwNPE() {
throw new NullPointerException();
}
Returning the value is handy in constructors:
import static pkg.Check.nonnull;
class MyClass {
#Nonnull private final String thing;
public MyClass(#Nonnull String thing) {
this.thing = nonnull(thing);
}
...
I don't see a great deal of point in doing this. You're simply replicating behaviour that you'd get for free the first time you try to operate on a, b or c.
It depends if you expect any of your arguments to be null - more precisely, if your method can still make a correct decision if some parameters are null.
If not, it's good practice to check for null and raise an exception, because otherwise you'll get a NullPointerException, which you should never catch, as its appearance always indicates that you forgot to check your variables in your code. (and if you catch it, you might miss other occurrences of it being thrown, and you may introduce bugs).
On the other hand, if you throw RunTimeException or some other custom exception, you could then handle it somewhere on the upstream, so that you have more control over what goes on.
Yes, public methods should scrub the input, especially if bad input could cause problems within your method's code. It's a good idea to fail fast; that is, check as soon as possible. Java 7 added a new Objects class that makes it easy to check for null parameters and include a customized message:
public final void doSomething(String s)
{
Objects.requireNonNull(s, "The input String cannot be null");
// rest of your code goes here...
}
This will throw a NullPointerException.
Javadocs for the Objects class: http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html
It depends on what your code is trying to do and the situation in which you want to throw an Exception. Sometime you will want your method to always throw an Exception if your method will not be able to work properly with null values. If your method can work around null values then its probably not necessary to throw an Exception.
Adding too many checked Exceptions can make for very convoluted and complicated code. This was the reason that they were not included in C#.
No, you shouldn't do that universally.
My preferences, in order, would be:
Do something sensible with the null. The sensible thing to do depends entirely on the situation, but throwing a custom exception should not be your first choice.
Use an assertion to check for null and test thoroughly, eliminating any situations in which null input is produced since - a.k.a bugs.
For public APIs, document that null isn't allowed and let it fail with an NPE.
You should never throw a runtime exception unless it is truly a fatal condition for the operation of the system, such as missing critical runtime parameters, but even then this is questionable as the system should just not start.
What are the business rules? Is null allowed for the field? Is it not?
In any case, it is always good practice to CHECK for nulls on ANY parameters passed in before you attempt to operate on them, so you don't get NullPointerExceptions when someone passes you bad data.
If you don't know whether you should do it, the chances are, you don't need to do it.
JDK sources, and Joshua Bloch's book, are terrible examples to follow, because they are targeting very different audiences. How many of us are writing public APIs for millions of programmers?
I have seen both of these when checking the equality of two Java String's:
// Method A
String string1;
// ...
if("MyString".equals(string1)) {
// ...
}
and
// Method B
String string1;
// ...
if(string1.equals("MyString")) {
// ...
}
My question is: which one is better and more widely used?
If you are sure that string1 can never be null then option 2 is readable and preferred. Otherwise option 1. Intention of option 1 is to avoid potential null pointer.
Method A won't throw a null pointer exception. There is no better of the two. It depends on whether on not you want it to throw a npe (and you might want that in your overall design).
Method B will fail with NullPointerException on null string1, whereas Method A will never throw this. Some authorities mandate this "defensive" programming. They have influenced me to do it, though it still does not come naturally!
It's also possible to write
if (string1 != null && string1.equals("MyString")) ...
though tools such as FindBugs flags this as a possible error, assuming that you should have made sure that string1 was already non-null. (Can you rely on the order of evaluation?).
So there are different schools of thought.
Method a does not throw NullPointerException and hence very convenient. It is widely used also.
Exceptions are for exceptional processing and have more overhead than checking for error conditions and handling them with regular logic. If you have been programming for a decade a NPE is a cringe matter which usually indicates careless code. Avoid them by using "constant".equals(variable) and people who read your code and use it will be happier.
The second one is more widely used. Neither is better.
It's the same idea as
if (1 == x)
but without a specific reason. but for a different reason. (Null pointer as noted by others).
I have always understood there to be two types of equality in Java,
value equality : uses the .equals() method to test that two objects implement an equivalence relation on non-null object references.
reference equality : uses the == operator to test that two primitive types or memory locations are equal.
The following pages describe these language fundamentals in more detail.
Wikibooks Java Programming : Java Programming/Comparing Objects
xyzws Java EE FAQ : What are the differences between the equality operator and the equals method?
Java Platform API : Javadoc for Object.equals()
Java Language Specification : Equality Operators
What none of these links explicitly specify is what should happen if two null object references are compared for value equality. The implicit assumption is that a NullPointerException should be thrown but this is not what is done by the ObjectUtils.equals() method, which might be considered a best practice utility method.
What worries me is that Apache Commons seems to have effectively introduced a third measure of equality into Java by the back door and that the already confusing state of affairs might have been made greatly more complex. I call it a third measure of equality because it attempts to test for value equality and when that fails it falls back to testing for reference equality. The Apache Commons equality test has many similarities with the value equality and reference equality but is also distinctly different.
Am I right to be concerned and to want to avoid using the ObjectUtils.equals() where ever possible?
Is there an argument for claiming that ObjectUtils.equals() provides a useful union of the other two measures of equality?
Chosen Answer
There doesn't seem to be a consensus opinion on this question but I decided to mark Bozho's as correct because he best drew my attention to what I now see as the greatest problem with null-safe equals checks. We should all be writing fail-fast code that addresses the root cause of why two null objects are being compared for value equality rather than trying to sweep the problem under the carpet.
Here's the code of ObjectUtils.equals(..):
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
ObjecUtils docs state clearly that objects passed can be null.
Now on the matter whether true should be returned if you compare two nulls. In my opinion - no, because:
when you compare two objects, you are probably going to do something with them later on. This will lead to a NullPointerException
passing two nulls to compare means that they got from somewhere instead of "real" objects, perhaps due to some problem. In that case comparing them alone is wrong - the program flow should have halted before that.
In a custom library we're using here we have a method called equalOrBothNull() - which differs from the equals method in this utility in the null comparison.
Am I right to be concerned and to want
to avoid using the
ObjectUtils.equals() where ever
possible?
No. What you need to consider equals depends on your requirements. And wanting to consider two nulls equal and any non-null unequal to a null without having to deal with NullPointerExceptions is a very, very common requirement (e.g. when you want to fire value-change events from a setter).
Actually, it's how equals() in general should work, and typically, half of that behvaiour is implemented (the API doc of Object.equals() states "For any non-null reference value x, x.equals(null) should return false.") - that it doesn't work the other way round is mainly due to technical restrictions (the language was designed without multiple dispatch to be simpler).
If you are concerned about this then you could either 1) not use this method 2) write your own to wrap it
public class MyObjectUtils {
public static boolean equals(Object obj1, Object obj2) {
return obj1 != null && obj2 != null && ObjectUtils.equals(obj1, obj2);
}
}
To me it seems weird to allow for null to be equals to null, but this doesn't seem like a large problem. For the most part, I wouldn't expect my application to even get into code paths that involve equality tests if one or more objects are null.