> On Aug 20, 2020, at 6:14 PM, Brian Goetz <brian.go...@oracle.com> wrote:
>
> I suspect there are other orderings too, such as "any nulls beat any novels"
> or vice versa, which would also be deterministic and potentially more natural
> to the user. But before we go there, I want to make sure we have something
> where users can understand the exceptions that are thrown without too much
> head-scratching.
>
> If a user had:
>
> case Box(Head)
> case Box(Tail)
>
> and a Box(null) arrived unexpectedly at the switch, would NPE really be what
> they expect? An NPE happens when you _dereference_ a null. But no one is
> deferencing anything here; it's just that Box(null) fell into that middle
> space of "well, you didn't really cover it, but it's such a silly case that I
> didn't want to make you cover it either, but here we are and we have to do
> something." So maybe want some sort of SillyCaseException (perhaps with a
> less silly name) for at least the null residue.
I believe that if Head and Tail exhaustively cover an enum or sealed type (as
was the intended implication of my example)—more generally, in a situation that
is optimistically total---then the user would be very happy to have some sort
of error signaled if some other value shows up unexpectedly in a statement
switch, whether that value is “Ankle" or “null”. Maybe a new error name would
be appropriate, such as UnexpectedNull.
If the user does not want such implicit handling of an optimistically total
situation in a statement switch, then it is always possible to provide explicit
clauses “case null: break;” and “default: break;”.
> On the other hand, ICCE for Box(novel) does seem reasonable because the world
> really has changed in an incompatible way since the user wrote the code, and
> they probably do want to be alerted to the fact that their code is out of
> sync with the world.
Yep.
> Separately (but not really separately), I'd like to refine my claim that
> `switch` is null-hostile. In reality, `switch` NPEs on null in three cases:
> a null enum, String, or primitive box. And, in each of these cases, it NPEs
> because (the implementation) really does dereference the target! For a
> `String`, it calls `hashCode()`. For an `enum`, it calls `ordinal()`. And
> for a box, it calls `xxxValue()`. It is _those_ methods that NPE, not the
> switch. (Yes, we could have designed it so that the implementation did a
> null check before calling those things.)