Switch on java.lang.Class
Brian Goetz
brian.goetz at oracle.com
Tue Apr 10 12:25:48 UTC 2018
> Though I don't see why usefulness of the feature in a low-level
> libraries should be the warning sign.
I don't dispute it's usefulness, but I'm sure you agree that "usefulness
> 0" is not the bar for putting a feature in the language -- it is way,
way higher than that.
My bigger concern is that it is error-prone -- especially if we release
type-test patterns and Class constant patterns at the same time. Many
users will be tempted to use Class patterns as a less ugly alternative
to instanceof tests -- and then their code will be subtly wrong. When
given the choice of what looks like "old fashioned switch with a new
type", and "new-fangled type-test patterns", many users will lean
towards the former because its familiar. And get the wrong thing.
So the problem is not that its only useful to low-level users; its that
others users may be tempted to use it, and get the wrong thing. (This
isn't theoretical. "Type Switch" has been an RFE for years; in the
examples presented as justification for the feature, many wrongly
conflate it with instanceof.)
> In any case I'm pretty sure that switch on class will be more
> applicable, than the switch on floats. But you are doing theswitch on
> floats. Why? For consistency, of course. You want to support all
> literals in switch. But class literals are also literals, according to
> JLS 15.8.2, so it is inconsistent not to support them (especially
> taking into account that their usefulness is not the lowest of all
> possible literals).
"For consistency" arguments are always weak justifications for including
a feature, because you can always find a precedent or rule to be
consistent with. The justification is not merely for consistency; it is
to avoid introducing _new_ asymmetries. It would be silly to not allow
float literals as patterns; then you couldn't match against
`Complex(0.0f, 0.0f)`.
So the choice is not about float in _switch_, but about float as a
_pattern_. Once you admit the latter, it is hard to say no to the
former. (Same with null; we're not doing `case null` for its own sake,
its to support `null` as a pattern; using it in `case` is a consequence
of that.)
So, should class literals be a pattern? That would also mean that you
could say
if (x instanceof Foo.class) { ... }
and it would mean something subtly different than
if (x instanceof Foo) { ... }
That's not so good. Or the same mistake in switch:
switch (anObject) {
case "Foo":
case String.class:
...
}
which means "does anObject equal the constant String.class". The
confusion between `String` and `String.class` as patterns is a pretty
serious risk. And again, introducing both kinds of patterns at once
makes it worse.
So, while I think its a consistent and useful feature, I also don't
think its a necessarily good idea to expose everyone to this confusion.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20180410/da6979e3/attachment.html>
More information about the amber-spec-experts
mailing list