Related
If I try to do a .equals() on a null string in java, a null pointer exception will be thrown. I am wondering, if I am trying to compare if a string is equal to some constant string, can I do the following:
MY_CONSTANT_STRING.equals(aStringVariable)
I know it will work, but is this just really poor code?
This is a standard Java idiom jokingly called a Yoda condition.
Personally I prefer to handle the null case explicitly, but the Yoda way is used a lot and any experienced Java programmer should be able to understand what is going on immediately. It's fine to use.
is this just really poor code?
No, this is the way many people would code the statement to avoid NPE.
What you've got is fine. It's even possible to use a String literal.
if( "value".equals(variable) ) {
...
If you don't like that, you can always explicitly check for null and equality, and combine the two checks with &&. The short circuiting of the operator will make sure you never get a NPE.
if( (variable != null) && variable.equals("value") ) {
...
I would keep the "CONSTANT.equals(possibleNull)" code without the null test only if it is a normal condition that the variable could be null - for instance because it just came out of a property map.
Similarly you can get away with not checking for null in instanceof-checks - like:
Food dinner = map.get("dinner");
if (dinner instanceof Soup) {
((Soup)blah).eat();
} // We don't care if it is a Fish or null
But if you really did not expect null, you should explicitly check for that in a separate if-test, and handle it appropriately. It's generally better to catch such data errors early rather than later.
Nope, it's usually done to avoid NPE. However, I usually prefer to do explicit check for null.
If you are concerned about the quality of your code, write a helper class that takes care of equality test:
public class ObjectHelper {
public static boolean testEquality(Object o1, Object o2) {
if (o1 == null && o2 == null) return true;
if (o1 == null) return false;
return o1.equals(o2);
}
}
Then use it like this:
if (ObjectHelper.testEquality(aStringVariable, My_CONSTANT_STRING))
Your so-called constant MIGHT stop being constant. It might be read from a configuration file some time in the future.
This question already has answers here:
object==null or null==object?
(11 answers)
Closed 4 years ago.
What is the difference between the two? Which one is better? I was asked this in an Interview.
The only difference I can think of is that if you wanted to do if(null == object) and forgot to add == and added =, it will not have any side-effect to your program. But if you do this mistake while doing if(object = null) then your program is toast.
Adding to Nayuki's answer, if the programmer mistypes = for ==, like if (object = null), there are still few cases where compilation error won't come and bugs would creep in the code.
For example: if (boolean1 = boolean2), is an assignment expression first and then is evaluated for the if condition. Another problematic code is if (wrapperBool = null), where wrapperBool is a Boolean wrapper class variable. It will throw a NullPointerException (NPE) at runtime.
But as Benny mentioned, mistyping should be caught upfront with unit test case(s).
In the Java programming language, the two expressions if (object == null) versus if (null == object) do exactly the same thing, because the == operator is commutative. The former notation is considered more natural when spoken in English, whereas the latter notation has some proponents.
If the programmer mistypes = for ==, like if (object = null), this is a compile-time error in Java because the condition expression must be a boolean value, not Object. Hence, if (object == null) and if (null == object) are equally secure against typos in Java.
But in C and C++, integer, floating-point, and pointer types are implicitly coerced to bool in a condition expression. Writing if (object = null) will compile but do the wrong thing, whereas writing if (null = object) should trigger a compile-time error.
See also: https://coderanch.com/t/489740/java/difference-null-object-object-null
Because of its commutative property, the only difference between object == null and null == object (the Yoda version) is of cognitive nature: how the code is read and digested by the reader. I don't know the definitive answer though, but I do know I personally prefer comparing the object I'm inspecting to something else, rather than comparing something else to the object I'm inspecting, if that makes any sense. Start with the subject, then the value to compare it to.
In some other languages this comparison style is more useful.
To safe guard against a missing "=" sign in general though, I think writing null == object is a misguided act of defensive programming. The better way around this particular code is by guaranteeing the behavior with a junit test. Remember, the possible mistake of missing an "=" is not dependant on the method's input arguments - you are not dependent on the right use of this API by other people - so a junit test is perfect to safe guard against that instead. Anyway you will want to write junit tests to verify the behavior; a missing "=" naturally falls within scope.
Or maybe, could it have been a trick question to get you on the topic of discussing the uses of Optional to avoid raw null-checks altogether?
This question already has answers here:
object==null or null==object?
(11 answers)
Closed 7 years ago.
I have seen various codes of my seniors and they have used this at many places.What effect does it have? why cant they include anything != null. This is true for below thing too
"true".equals(x).
Why is this so?
anything != null is exactly equivalent to null != anything.
On the other hand, "true".equals(x) avoids the need to check if x is null when doing x.equals("true").
The reason for including constants on the left hand side of an equals expression is to avoid NullPointerException even when the variable is null. This also improves the readability of the expression.
That being said, null!=something is a personal choice and I would prefer using something!=null.
These are two separate practices.
Using null on the left side when comparing to null ensures that you won't, by mistake, use = instead of ==. However, this is a practice taken from languages other than Java, as in Java the expression
if ( something = null )
is going to fail as it does not resolve to a boolean value. In other languages it may be permissible to use a condition whose value is actually a pointer.
Thus this practice has no meaning in Java.
The second practice, as you were told, has to do with preventing a NullPointerException. It should be noted that this practice is controversial, because it allows a null to propagate to a later point in the program, and that usually means that it will be harder to find when it causes a bug.
This is called a Yoda condition. Among other things, it helps prevent an accidental assignment due to a missing = or !, as in foo = null. The reverse, null = foo, would not even compile.
That said, it is purely a stylistic preference. foo != null is logically equivalent to null != foo.
That check is so the program ensures the variable in question has been initialized before reading it. If a program tries to access a null variable, it will crash (specifically in Java it will throw a NullPointerException). It is a critical aspect of defensive programming.
As far as ordering, the evaluation of whether something is null or not is commutative. Meaning:
something != null
Is the same as
null != something
It is all a matter of personal preference. And as #manouti explains above, "true".equals(x) avoids the need to check if x is null when doing x.equals("true"), so you save a line of code.
Seems that some people prefer null != anything, because anything might be quite long expression, so writing null first makes it visible in the narrow window and simplifies code reading ("ok, we just check if something is not null"). But it's totally a matter of style.
As for "true".equals(x), it's well explained by #manouti.
I'm reviewing a manual of best practices and recommendation coding java I think is doubtful.
Recomendation:
String variable;
"xx".equals(variable) // OK
variable.equals("xx") //Not recomended
Because prevents appearance of NullPointerException that are not controlled
Is this true?
This is a very common technique that causes the test to return false if the variable is null instead of throwing a NullPointerException. But I guess I'll be different and say that I wouldn't regard this as a recommendation that you always should follow.
I definitely think it is something that all Java programmers should be aware of as it is a common idiom.
It's also a useful technique to make code more concise (you can handle the null and not null case at the same time).
But:
It makes your code harder to read: "If blue is the sky..."
If you have just checked that your argument is not null on the previous line then it is unnecessary.
If you forgot to test for null and someone does come with a null argument that you weren't expecting it then a NullPointerException is not necessarily the worst possible outcome. Pretending everything is OK and carrying until it eventually fails later is not really a better alternative. Failing fast is good.
Personally I don't think usage of this technique should be required in all cases. I think it should be left to the programmer's judgement on a case-by-case basis. The important thing is to make sure you've handled the null case in an appropriate manner and how you do that depends on the situation. Checking correct handling of null values could be part of the testing / code review guidelines.
It is true. If variable is null in your example,
variable.equals("xx");
will throw a NPE because you can't call a method (equals) on a null object. But
"xx".equals(variable);
will just return false without error.
Actually, I think that the original recommendation is true. If you use variable.equals("xx"), then you will get a NullPointerException if variable is null. Putting the constant string on the left hand side avoids this possibility.
It's up to you whether this defense is worth the pain of what many people consider an unnatural idiom.
This is a common technique used in Java (and C#) programs. The first form avoids the null pointer exception because the .equals() method is called on the constant string "xx", which is never null. A non-null string compared to a null is false.
If you know that variable will never be null (and your program is incorrect in some other way if it is ever null), then using variable.equals("xx") is fine.
It's true that using any propertie of an object that way helps you to avoid the NPE.
But that's why we have Exceptions, to handle those kind of thing.
Maybe if you use "xx".equals(variable) you would never know if the value of variable is null or just isn't equal to "xx". IMO it's best to know that you are getting a null value in your variable, so you can reasign it, rather than just ignore it.
You are correct about the order of the check--if the variable is null, calling .equals on the string constant will prevent an NPE--but I'm not sure I consider this a good idea; Personally I call it "slop".
Slop is when you don't detect an abnormal condition but in fact create habits to personally avoid it's detection. Passing around a null as a string for an extended period of time will eventually lead to errors that may be obscure and hard to find.
Coding for slop is the opposite of "Fail fast fail hard".
Using a null as a string can occasionally make a great "Special" value, but the fact that you are trying to compare it to something indicates that your understanding of the system is incomplete (at best)--the sooner you find this fact out, the better.
On the other hand, making all variables final by default, using Generics and minimizing visibility of all objects/methods are habits that reduce slop.
If you need to check for null, I find this better readable than
if (variable != null && variable.equals("xx")). It's more a matter of personal preference.
As a side note, here is a design pattern where this code recommendation might not make any difference, since the String (i.e. Optional<String>) is never null because of the .isPresent() call from the design pattern:
Optional<String> gender = Optional.of("MALE");
if (gender.isPresent()) {
System.out.println("Value available.");
} else {
System.out.println("Value not available.");
}
gender.ifPresent(g -> System.out.println("Consumer: equals: " + g.equals("whatever")));
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.