New JEP: Switch Expressions for the Java Language

Brian Goetz brian.goetz at
Fri Dec 8 15:01:06 UTC 2017

On 12/7/2017 6:28 PM, Liam Miller-Cushon wrote:
> I don't see it mentioned in the JEP, but will the default case of an 
> expression switch be required to be last? (Previously: 

We've not fully worked through these details yet.  Here's my current 

We don't want to bifurcate the world into legacy switch and new switch.  
Instead, we'd like to generalize switch, and then, where something makes 
sense for (say) int switch but not for the general case, specify those 
restrictions in terms of what's in the case labels.  (For example (not 
saying we will do this), take fallthrough.  If we decided we were going 
to kill fallthrough in patterns, rather than saying "no fallthrough in 
pattern switch", we'd say "no falling into patterns of XYZ kind.")

The so-called-legacy switches have an interesting property; all their 
cases, other than default, are mutually exclusive.  (If you match "foo", 
you can't match "bar".)  This means that ordering is irrelevant (modulo 
fallthrough.)  OTOH, with more interesting switches, a case can subsume 
another case, so its important that they be put in the right order 
(having "case Object" before "case String" would mean the latter is 
dead, and we treat this as an error.)  In this light, "default" means 
"case anything else", so if there's even a tiny bit of room for 
confusion, it should go last.

What we do about existing switches is still open.  For consistency[1], 
we might want to remake the world to say "default goes last."  But, this 
has a cost (needless code churn, which will be viewed as ceremony), and 
its not clear the consistency benefit is warranted.  So we might say 
something like "if any case label in the switch has a defined dominance 
ordering with any other case label, default must be the last case."  
That way old code continues to work, but once you migrate to nontrivial 
patterns (which involves source changes anyway), you need to put things 
right.  This seems a good compromise.

For expression switch, we can be a little stricter, since there's no 
existing code.  On the other hand, its good to have the same set of 
rules for expression and statement switch (all things being equal). So 
this could go either way.

[1] Language-evolution arguments that start with "for consistency, ..." 
are usually weak.

> > in the case of an enum switch that covers all known cases, a default 
> clause can be inserted by the compiler that indicates that the enum 
> definition has changed between compile time and runtime
> This sounds great, but note that it makes adding values to an enum a 
> potentially source-incompatible change. Pattern switches that handle 
> all values of an enum will need to be updated to handle the new value, 
> or to have an explicit default.

Yes, but that doesn't bother me so much.  Adding a member to an enum 
that is exposed across compilation unit boundaries should be an unusual 
case.  If someone has explicitly coded defensively to deal with this, 
great.  If they haven't, having their switch code break when someone 
else changes an assumption out from under them is a good thing.

Users (rightly) find it irritating that, when they define an enum:

     enum TrafficLight { RED, YELLOW, GREEN }

that they constantly have to deal with "might be some other color." Not 
all enums have this characteristic, but many do, and I think its 
reasonable to let users err on the side of this assumption.  They can 
always code an explicit default if they want.

More information about the amber-spec-experts mailing list