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()))