Overall, Java's compiler is an impressive piece of software (not nearly as impressive as the JVM, though) that has no doubt saved me from countless hours hunting down runtime issues. Nevertheless, there are times when the compiler makes me sad.
if (obj instanceof Foo) {
((Foo) obj).foo();
}
Why it's sad: given improvements in the compiler's type inferrence ability, it would seem within reason to support flow-sensitive typing. If the condition that obj
is an instance of Foo proves true, this information should "flow" into the if
body. But no, the compiler still requires an explicit cast on the object in order to use the methods of the Foo type. If you’re a JVM user desperate for flow-sensitive typing, check out Kotlin (or Ceylon).
boolean elusiveSwitchDefault(DayOfWeek day) {
switch (day) {
case SUNDAY:
case MODNAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
case SATURDAY:
return true;
default:
return false;
}
}
Why it's sad Clearly, all possible values of the DayOfWeek
enumeration are being accounted for in the case statement, therefore there is never an occassion for the default
statement to execute.
Why it's not that sad First off, enumerations may change over time. If your switch statement is compiled prior to a new enum value being added, then all of a sudden there is a possibility the default
case would execute.
int impossibleElse(boolean condition) {
if (condition) {
return 1;
} else if (!condition) {
return 2;
} else {
return 3;
}
}
boolean nasty(Object obj) {
return obj == null ? null : true;
}
Why this is sad? This shouldn't even compile, in my opinion. Clearly one part of the ternary operator evaluates to a primitive--why should it be allowed that the other path be null
? Because it does, when the compiler tries to auto un-box the resulting null Boolean
into a primitive boolean
, null pointer exception hilarity ensures.
Not a compiler issue per-se, but wanted to throw this in:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
throw new RuntimeException();
}
});
I didn't realize this until recently, but you can override the default exception handler. The funny thing is, if you throw an Error/Exception from this handler, guess what? The runtime handles it! So yes, there is a default default exception hanlder that handles the exceptions thrown by the default exception handler. Ha!