Behavior of Switch Statements without fallthrough
Liam Miller-Cushon
cushon at google.com
Tue Jul 22 15:46:06 UTC 2025
I think I'm mostly agreeing here, but note that the second example isn't an
enhanced switch statement because it isn't a statement. 14.11.2 defines
'enhanced switch *statements*', the 'enhanced' concept doesn't apply to
switch expressions.
15.28.1 defines additional rules for switch expressions and says they are
required to be exhaustive and always get the MatchException.
On Tue, Jul 22, 2025 at 8:32 AM Cay Horstmann <cay.horstmann at gmail.com>
wrote:
> 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20250722/ce4f39b0/attachment-0001.htm>
More information about the amber-dev
mailing list