Expression switch exception naming

Kevin Bourrillion kevinb at
Fri Mar 30 17:37:26 UTC 2018

Although the depth of this debate may seem to have exceeded its value in
resolving the question at hand, I think it's usually worthwhile to try
hammer out these kinds of differences, until we all have a greater common
understanding (or clearly arrive at an impasse...).

On Fri, Mar 30, 2018 at 9:32 AM, Brian Goetz <brian.goetz at> wrote:

Summarizing what I heard: seeing Error is your trigger to "go fix your
> classpath and recompile".  And implicitly, you're saying: if it is an
> exception (no matter how clearly worded about inconsistent assumptions
> across classes), it is far less likely to trigger this reaction?

More or less, though let's not debate the precise meaning of "far". :-) I
believe that developers would like to assume that
IncompatibleClassChangeError means what it says it means, and that the JDK
follows the Effective Java advice of always reusing appropriate exception

(And, we've told people for years that its OK to add enum constants.)
> Yes, but we are deciding to reverse that decision 15 years later. We're
> doing that because we think it's worth it, but let's at least be clear
> about the fact that that is what we're doing.
> Let's back up.  Are we really reversing this?   Or are we doing something
> more subtle?
> Is it OK to add enum constants if they are not published across
> maintenance boundaries?
> Is it OK to add enum constants if you don't use expression switches?
> Is it OK to add enum constants if you use expression switches with
> explicit defaults?

Like any other incompatible change, we can say "no, it's compatible as long
as callers aren't doing X Y Z...", or "it's not so bad if it's not
exported". The fact that there are these conditions at all is what makes it

(Note that I do concede that many types of changes we consider to be
source-compatible still *have* those conditions - e.g. if you add a method
someone might have been wildcard-static-importing from both you and another
class, that kind of thing -- but I think we generally deem them rare enough
to not be worth worrying about; that's not what we're talking about here.)

Suppose you publish an API that has
>     enum TrafficLight { RED, YELLOW, GREEN }
> And I depend on your API with an optimistically exhaustive switch (OES).
> Then you add BLUE**
> So, who's at fault?
>  - You, for adding a switch to an enum that is published across a
> maintenance boundary?
>  - Me, for OESing on an enum imported across a maintenance boundary?
>  - Java, for letting me OES across a maintenance boundary?

Just an observation: you've introduced the word "blame" and now "fault" to
this discussion, but I think they aren't the real point. I think the
relevant question is not "who's at fault" but "how do I proceed as quickly
as possible to fixing it".

Now, either this came to my attention through a compile-time or runtime
error. If the former, it is clear what is going on, and is part of my
normal workflow for how I get my code to work. If the latter, I'm
suggesting that the best thing we can do is to prompt the developer to
wonder "wait, why didn't I get a compile error?" so that it reduces to the

(The latter is a new idea, but I think is what you're getting at -- perhaps
> the rule should be that _within a module_, which is expected to be
> co-compiled, its OK to leave off the default, but for "foreign"
> enums/sealed types, we're not going to put any faith in the claim of
> sealed-ness, and make you handle the default explicitly?

I'm not sure I understand this, and therefore I suspect it's not what I'm
getting at. :-)

> **Note that just _adding_ an enum is not enough to trigger an error.
> Someone actually has to pass that enum to me.  And I have to switch on it.
> And that switch has to be optimistically exhaustive.

Same as with the decorator, right? Someone has to actually call the method.

Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at

More information about the amber-spec-observers mailing list