The compiler has no way of knowing that Assert.fail
will always throw an exception, unless it were to delve into the bytecode of that method and do some sort of static analysis on it (and once you start this sort of thing then where do you stop?). The Java Language Specification states (section 8.4.7)
If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally (§14.1).
where "can complete normally" in your example boils down to (section 14.21)
A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.
The last statement in your method is a switch
statement:
A switch statement can complete normally iff at least one of the following is true:
[...]
- The last statement in the switch block can complete normally.
The last statement in the switch
is an expression statement (a method call)
An expression statement can complete normally iff it is reachable.
i.e. the spec specifically states that the compiler shouldn't look inside any method calls, and any method call expression must be considered to be one that can complete normally.
The same section also defines that
A
break
,continue
,return
, orthrow
statement cannot complete normally.
So to keep the compiler happy you'll need to add a return or throw to the end of the method
// will never be reached
throw new Error();
I'd personally go for a throw, with a comment explaining that something has gone very wrong if this line is ever reached...