Behavior of Switch Statements without fallthrough

Cay Horstmann cay.horstmann at gmail.com
Tue Jul 22 15:32:39 UTC 2025


There is more to this.

Agreed that

boolean isScary(Bird bird) {
     switch (bird) {
         case TURKEY -> {
             return true;
         }
         case EAGLE -> {
             return true;
        }
        case WOODPECKER -> {
            return false;
        }
     }
}

is not an enhanced switch. But neither is

boolean isScary2(Bird bird) {
     return switch (bird) {
         case TURKEY -> true;
         case EAGLE -> true;
         case WOODPECKER -> false;
     };
}

Yet the second method compiles.

There is another rule, §14.22 (https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.22): ... a switch can complete normally if ... "The switch statement is not enhanced (§14.11.2) and its switch block does not contain a default label."

This rule applies only to switch statements, not to switch expressions.

IIRC, the thinking behind the treatment of switch statements in §14.22 was that the enum might change in a separate compilation unit. Then the switch simply completes without matching any cases. In contrast, for switch expressions (and enhanced switch statements), a MatchException is thrown in that situation.

In summary, here is what happens when no case applies to the selector:

               statement   expression
not enhanced  completes   throws ME
enhanced      throws ME   throws ME

As it says in JEP 361: The greater the divergence between switch expressions and switch statements, the more complex the language is to learn, and the more sharp edges there are for developers to cut themselves on.

Cheers,

Cay

Il 16/07/2025 17:49, Liam Miller-Cushon ha scritto:
> I think JLS 14.11.2 covers this:
> 
>  > An enhanced switch statement is one where ... there is a case ... null
> ...
>  > For compatibility reasons, switch statements that are not enhanced switch statements are not required to be exhaustive.
> 
> The first example without the 'case null' isn't an 'enhanced' switch, so it isn't required to be exhaustive, so it doesn't get the synthetic default that throws a MatchException.
> 
> https://bugs.openjdk.org/browse/JDK-8345997 <https://bugs.openjdk.org/browse/JDK-8345997> and https://mail.openjdk.org/pipermail/amber-dev/2024-December/009139.html <https://mail.openjdk.org/pipermail/amber-dev/2024-December/009139.html> cover similar ground.
> 
> On Wed, Jul 16, 2025 at 8:26 AM Ethan McCue <ethan at mccue.dev <mailto:ethan at mccue.dev>> wrote:
> 
>     I had a reader notice that the following code will not compile
> 
>     https://javabook.mccue.dev/switch/exhaustiveness <https://javabook.mccue.dev/switch/exhaustiveness>
> 
>     enum Bird {
>          TURKEY,
>          EAGLE,
>          WOODPECKER
>     }
> 
>     boolean isScary(Bird bird) {
>          switch (bird) {
>              case TURKEY -> {
>                  return true;
>              }
>              case EAGLE -> {
>                  return true;
>              }
>              case WOODPECKER -> {
>                  return false;
>              }
>          }
>     }
> 
>     void main() {}
> 
>     I can rationalize this by imagining that, in the case of a switch statement, there is no synthetic default inserted and thus it wouldn't be friendly to a new enum variant. That's not a spec-centered interpretation, but it would make sense to me.
> 
>     What doesn't make sense is that adding a case null allows it to compile
> 
>     enum Bird {
>          TURKEY,
>          EAGLE,
>          WOODPECKER
>     }
> 
>     boolean isScary(Bird bird) {
>          switch (bird) {
>              case TURKEY -> {
>                  return true;
>              }
>              case EAGLE -> {
>                  return true;
>              }
>              case WOODPECKER -> {
>                  return false;
>              }
>              case null -> {
>                  return true;
>              }
>          }
>     }
> 
>     void main() {}
> 
>     This was pointed out as potentially being the relevant part of the spec
> 
>     https://docs.oracle.com/javase/specs/jls/se24/html/jls-14.html#jls-14.11.1.1 <https://docs.oracle.com/javase/specs/jls/se24/html/jls-14.html#jls-14.11.1.1>
> 
> 
>     A set of case elements, P, covers a type T if one of the following cases applies:
>     P covers a type U where T and U have the same erasure.
>     P contains a pattern that is unconditional for T.
>     T is a type variable with upper bound B and P covers B.
>     T is an intersection type T1& ... &Tn and P covers Ti, for one of the types Ti (1≤ i ≤ n).
>     The type T is an enum class type E and P contains all of the names of the enum constants of E.
> 
> 

-- 

Cay S. Horstmann | https://horstmann.com



More information about the amber-dev mailing list