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.