As part of an investigation into the parameters of a method, I tried the new Pattern Matching for switch (Preview). Using a traditional condition, it works perfectly:
Method firstMethod = BitSet.class.getDeclaredMethods()[0];
Parameter firstParameter = firstMethod.getParameters()[0];
if (firstParameter.getType() == Integer.class) {
System.out.println("Integer");
}
When I tried to refactor it to use a switch
statement, it did not compile:
Method firstMethod = BitSet.class.getDeclaredMethods()[0];
Parameter firstParameter = firstMethod.getParameters()[0];
switch (firstParameter.getType()) {
case Integer.class: System.out.println("Integer");
case int.class: System.out.println("int");
default: System.out.println("other");
}
The error is:
error: incompatible types: Class<Integer> cannot be converted to Class<CAP#1>
case Integer.class: System.out.println("Integer");
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
Is this something that can't be done, or is it just a syntax error?
This is not how switching over types work. You can switch over an object’s actual type and have to specify type names, rather than Class
literals.
Object o = 42;
switch(o) {
case Integer i: System.out.println("Integer " + i); break;
case String s: System.out.println("String " + s); break;
default: System.out.println("other");
}
Note that with pattern matching, there is no fall-through support, so specifying break
is mandatory. Or you use the new syntax which has no fall-through in the first place
Object o = 42;
switch(o) {
case Integer i -> System.out.println("Integer " + i);
case String s -> System.out.println("String " + s);
default -> System.out.println("other");
}
The object returned by getType()
is always an instance of java.lang.Class
, so branching by its type makes no sense. This doesn’t mean that comparing the actual values with a switch
statement or expression was impossible. The comparison can be performed with a guarded pattern:
Method firstMethodWithParam = Arrays.stream(BitSet.class.getDeclaredMethods())
.filter(m -> m.getParameterCount() > 0)
.findAny().orElseThrow();
switch(firstMethodWithParam.getParameterTypes()[0]) {
case Class<?> cl && cl == Integer.class -> System.out.println("Integer");
case Class<?> cl && cl == int.class -> System.out.println("int");
case Class<?> cl && cl == String.class -> System.out.println("String");
case Class<?> cl && cl == long.class -> System.out.println("long");
case Class<?> cl && BitSet.class.isAssignableFrom(cl)
-> System.out.println("BitSet or subtype");
default -> System.out.println("other");
}
but that’s only for completeness. I think it’s obvious that this is no improvement over if
statements or a map from Class
to handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With