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.