Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ternary operator vs if/else in <JDK8 compatibility

Recently I'm reading the source code of Spring Framework. Something I can't understand goes here:

public Member getMember() {     // NOTE: no ternary expression to retain JDK <8 compatibility even when using     // the JDK 8 compiler (potentially selecting java.lang.reflect.Executable     // as common type, with that new base class not available on older JDKs)     if (this.method != null) {         return this.method;     }     else {         return this.constructor;     } } 

This method is a member of class org.springframework.core.MethodParameter. The code is easy to understand while the comments are hard.

NOTE: no ternary expression to retain JDK <8 compatibility even when using the JDK 8 compiler (potentially selecting java.lang.reflect.Executable as common type, with that new base class not available on older JDKs)

What's the difference between using ternary expression and using if...else... construct in this context?

like image 243
jddxf Avatar asked Sep 09 '15 08:09

jddxf


People also ask

Which is better if else or ternary operator in Java?

Moreover, as has been pointed out, at the byte code level there's really no difference between the ternary operator and if-then-else. As in the above example, the decision on which to choose is based wholly on readability.

Why use ternary operator instead of if else?

The conditional operator – also known as the ternary operator – is an alternative form of the if/else statement that helps you to write conditional code blocks in a more concise way. First, you need to write a conditional expression that evaluates into either true or false .

Is it good practice to use ternary operator in Java?

The ternary operator is a common tool that you'll see a lot in JavaScript code. It can make your code concise but it can also make your code unreadable if you don't use it properly. Try to keep the ternaries simple and readable.

Is ternary operator bad practice Java?

The conditional ternary operator can definitely be overused, and some find it quite unreadable. However, I find that it can be very clean in most situations that a boolean expression is expected, provided that its intent is clear.


1 Answers

When you think about the type of the operands, the problem becomes more apparent:

this.method != null ? this.method : this.constructor 

has as type the most specialized common type of both the operands, i.e. the most specialized type common to both this.method and this.constructor.

In Java 7 this is java.lang.reflect.Member, however the Java 8 class library introduces a new type java.lang.reflect.Executable which is more specialized than the generic Member. Hence with a Java 8 class library the result type of the ternary expression is Executable rather than Member.

Some (pre-release) versions of the Java 8 compiler seem to have produced an explicit reference to Executable inside generated code when compiling the ternary operator. This would trigger a class load, and thus in turn a ClassNotFoundException at runtime when running with a class library < JDK 8, because Executable only exists for JDK ≥ 8.

As noted by Tagir Valeev in this answer, this is actually a bug in pre-release versions of JDK 8 and has since been fixed, so both the if-else workaround and the explanatory comment are now obsolete.

Additional note: One might come to the conclusion that this compiler bug was present before Java 8. However, the byte code generated for the ternary by OpenJDK 7 is the same as the byte code generated by OpenJDK 8. In fact, the type of the expression goes completely unmentioned at runtime, the code is really only test, branch, load, return without any additional checks going on. So rest assured that this is not a problem (anymore) and indeed seems to have been a temporary problem during development of Java 8.

like image 185
dhke Avatar answered Sep 23 '22 08:09

dhke