Ternary operator evaluating conditional statement while condition not met - java

I have written some code; here the relevant snippets:
#NonNullByDefault
public class Score<NUMERAL, LITERAL>
{
protected NUMERAL value;
#Nullable
protected LITERAL literal;
[...]
I have overwritten my equals()method as follows:
#Override
public boolean equals(#Nullable Object object)
{
if(object == null) return false;
if(object == this) return true;
if( object instanceof Score)
{
return ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
literal == null ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral());
}
return false;
}
Basically, the idea is that a Score may only have a numeric value in which case the literal is null. I have written some unit tests and get a null pointer exception with the code below:
[....]
Score<Float, String> score = new Score<>(0.0f);
Score<Float, String> anotherScore = new Score<>(1.0f, "One");
[....]
assertFalse(score.equals(anotherScore));
If I am not mistaken, shouldn't short-cutting in equals prevent anything after the && from being executed as the first expression is already false? Furthermore, why the exception? As the conditional is true, I would expect the expression of the ternary to be evaluated and the conditional expression skipped. From what I have read in the specifications, this should be the behaviour. Furthermore, I found this question: Java ternary (immediate if) evaluation which should lend some more leverage to my thought process.
Maybe I have overlooked something rather obvious but I am out of ideas. Maybe you can help?

It short-circuits alright, but not quite the way you want it to. && has a higher precedence than the ternary ?: - therefore this (indentation, line breaks and comments added to clarify)
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
actually means this:
//the first line as a whole is the condition for ?:
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) && literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
This means, in practice, that if the first part of the condition is false but literal is null, you automatically enter the : part of the expression where you call literal.equals, causing the NullPointerException.
The fix is simple: add parentheses to tell Java which way you want stuff to be evaluated:
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
(literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral()))

Related

how do i make arrays equal if they have to be filled?

i am confused because I need my array to be equal to the other array but I don't know how to compare them without losing their values
If both roots are null you will get an undesired result based on what you're trying to do with your second if condition.
It looks like if both roots are null you want to return true, but you're returning false. You could use just one if statement
if(thisRoot == null || otherRoot == null){
return thisRoot == null && otherRoot == null;
}
You have a bigger problem with how you're comparing the data of the two nodes.
thisRoot.getData() != otherRoot.getData()
This comparison is not what I think you're looking for. Instead you should overrride the equals method for your data objects and compare using it instead
The order of your conditions causes a problem.
if (thisRoot == null || otherRoot == null) {
return false;
}
if (thisRoot == null && otherRoot == null) {
return true;
}
The first condition will evaluate to true (and lead to return false) even if both branches are null.
You should first evaluate if both branches are null; after that, you can check the case where only one of them is null.

return t == null ? -1 : t.height; what do ? and : mean?

I have encountered this piece of code to compute height of an AVL tree node:
private int height (AvlNode<T> t) {
return t == null ? -1 : t.height;
}
What do the ? and : mean?
This is a ternary operator. The general syntax is:
cond ? ifTrue : ifFalse
where cond is an expression returning a boolean value. The entire expression at large is evaluated to ifTrue when cond is true, otherwise it is evaluated to ifFalse. Of course, both ifTrue and ifFalse must be of compatible types (note that null is possible for objects).
The code above is, in practice, exactly equivalent to the following:
if (t == null)
return -1;
return t.height;
This is a very classical operator found in many languages. One language which does NOT have this operator is Python.
it is like a if test.
your example is similar to this code:
if (t == null) return -1;
else return t.height;
It is equivalent to:
if (t==null)
return -1;
else
return t.height;
The conditional operator ? :
Is used to return the result of either expressions depending on the value of the 1st expression.
It works by evaluating boolean expr and then deciding which expression to evaluate.
if t is null it will return -1, else it will return t.hight. This is a cleaner way to implement null check instead of having
if(t==null)
return -1
else
return t.hight
but it might look more cryptic then the "if approach"
(a > b) ? a : b;
is an expression which returns one of two values, a
or b. The condition, (a > b), is tested. If it is true the first
value, a, is returned. If it is false, the second value, b, is
returned. Whichever value is returned is dependent on the conditional
test, a > b. The condition can be any expression which returns a
boolean value.

Is this a good IF block?

Are these comparisons always safe from creating a NullPointer Exception ?
if( myObject == null || myObject.someMethod() == someValue )
{
if( myObject == null && myObject.getAlwaysTrue() )
{
}
}
Is there some directional precedence in java for condition evaluation, apart from short circuiting ?
UPDATE: I Know myObject.anything() will throw a NullPointer. Its just that I have come across such code by other programmers, and I want to know if there's a safe way of squeezing multiple checks along with a null check in a single condition. I'm looking for a good rule to stick to.
No, this line is not safe:
if( myObject == null && myObject.getAlwaysTrue() )
If you know that myObject is null then you shouldn't try to dereference it. If however you wrote this:
if( myObject != null && myObject.getAlwaysTrue() )
Then it would be safe. This is because && (and || for that matter) has short-circuit evaluation. If you write a && b and the expression a evaluates to false, then the expression b is not evaluated so it will not throw an exception. The left operand is always evaluated first.
Why not separate out the gating issue?
if (myObject != null) {
if ((myObject.someMethod() == someValue) && myObject.getAlwaysTrue()) {
}
}
if( myObject == null && myObject.getAlwaysTrue() )
This will cause you a NullPointerException when myObject is null
Wherever I can, I strive for less indentantion and complex "ifology". In your case I'd just write
if (myObject == null) return;
... go on knowing that myObject is not null...
If the myObject is null, myObject.getAlwaysTrue() in the second if statement will always result in NullPointerException.
In the case of || the if expression evaluates the boolean expressions until it finds the first one that's true.
With && the if expression evaluates the boolean expressions until it finds the first one that's false.
So in your case when myObject is null, you'll get the following evaluations:
First if:
myObject == null -> true
Second if:
myObject == null -> true
myObject.getAlwaysTrue() -> NullPointerException
This is not :
if( myObject == null && myObject.getAlwaysTrue() )
&& will check both conditions, myObject.getAlwaysTrue() will throw NullPointerException if myObject is null.

Difference between these two appraoch in calling equals method?

Approach one.
if (graphType.equals("All") || graphType.equals("ALL"))
Aprroach two.
if ("All".equals(graphType) || "ALL".equals(graphType))
What is the difference between these two approaches?
Why the below one is better?
The second one is better, as if graphType is null, the first code snippet will throw a NullPointerException.
Note that you can simplify your code using "ALL".equalsIgnoreCase(graphType) (if you accept values such as AlL or aLL...)
Edit regarding your comment:
If graphType is null, in the first case, you will get a NullPointerException. In the second case, the evaluation of the equals method will be false, as "someString".equals(null); always returns false:
Here is the code of the String.equals(String) method:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
(source)
The interesting line is if (anObject instanceof String) {. When you call the instanceof statement on a null object, this test always returns false. That's why "anyString".equals(null); will return false.
I feel the need to present a contrarian viewpoint to the accepted answer:
The first one is better, precisely because it will throw a NullPointerException in the case where graphType is null.
Generally, if an unexpected condition is found, you want to halt and throw an Exception as early as possible, otherwise you may continue to execute the program in an invalid state and the bug may become fiendishly difficult to track down.
This is sometimes referred to as the "fail-fast" principle.
romaintaz answer is absolutely correct. However, if you're like me, you might prefer to use the first approach to make your code easier to read. This is where assertions come into play:
assert graphType != null : "graphType is null";
if (graphType.equals("All") || graphType.equals("ALL"))
The question is whether your users will find a creative way to make graphType = null once you've finished testing.
The other thing I don't like about the second approach is that it fails silently in the case that graphType is unexpectedly null -- It prevents a runtime error, but may present a bug that's difficult to track down.

Equality comparison -- any saner way?

How do I implement this equality comparison is a sane java way?
boolean x = (a == b) || (a.equals(b))
I want to make sure the content of both objects is equal but null is also ok, i.e. both can be null and are thus equal.
Update: just to be clear, I have to implement this comparison several times and don't want to copy&paste this stuff every time, especially with lenghty object names. With 'a' and 'b' it looks small and simple, but tends to grow... I'd like to know if I'm missing some existing Java feature for this.
You might want to have a look at the always useful Apache Commons Lang, more precisely ObjectUtils.equals().
Another way to do
boolean x = null==a ? null==b : a.equals(b);
The typical pattern is:
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
// Now deal with a and b, knowing that they are non-identical, non-null references
Yes, it's wordy - but if you separate it out into its own method, you can keep it under reasonable control.
What happens if a is null but b is not? I think you really want:
boolean x = (a == null && b == null) || (a != null && a.equals(b))
EDIT: You could implement a static NullEquals method for the class that takes two objects of that class and does the comparison as above to avoid rewriting and make the code a little cleaner.
public class MyClass {
public static boolean NullEquals( MyClass a, MyClass b )
{
return (a == null && b == null) || (a != null && a.equals(b));
}
}
if (MyClass.NullEquals(a,b))
{
...
}
Not a direct answer, but if you have lot of objects that can be or not null, may be that indicates some problem with your code. Take a look at the Null Pattern , that is an alternative way to represent the absence of an object
What about:
boolean x = equals( a, b );
public static boolean equals( Object a, Object b ) {
if ( a == null && a == b ) {
return true;
} else {
return a == b || a.equals( b );
}
}
Let me see.
if a is null and a is b then it's ok
if a is not null then if a == b ( same ref ) return true by shortcircuit
if a is not b ( 2dns part of the OR probably b is null ) then return a ( not null ) .equals( b ) whatever b is
Yeap covered.
Can not add comment,
Treat this as comment to Jon Skeet's answer.
Does Null = Null true or false in Java.
More specifically what should be Null = Null should be treated and How and why the different language treat this case ?
The most common way of doing it is:
a==null ? b==null : a.equals(b)
A potentially slightly more efficient, but less clear, expressions is:
a==b || (a!=null && a.equals(b))
You can of course put this inside a method:
public static boolean eq(Object a, Object b) {
return a==b || (a!=null && a.equals(b));
}
Note the original question code NPEs if a is null and b is non-null.
For performance reasons, usually it is good to check for identity before executing any other logic, as was done in the question. However, many of the answers don't take this into account.
The best place to put the identity check is in the implementation of the equals method on your class:
public boolean equals(Object obj) {
if(this == obj) return true;
...
}
If this has/can be done, you can do the comparison easily:
a == null ? b == null : a.equals(b);
Otherwise you might have to check for identity yourself:
a == null ? b == null : (a == b || a.equals(b));

Categories

Resources