是否可以将 Class<?> 与新的模式匹配开关一起使用?
Is it possible to use Class<?> with the new Pattern-Matching switch?
作为对方法参数调查的一部分,我尝试了新的 Pattern Matching for switch (Preview)。使用传统条件,它完美地工作:
Method firstMethod = BitSet.class.getDeclaredMethods()[0];
Parameter firstParameter = firstMethod.getParameters()[0];
if (firstParameter.getType() == Integer.class) {
System.out.println("Integer");
}
当我试图重构它以使用 switch
语句时,它没有编译:
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");
}
错误是:
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 ?
这是无法完成的事情,还是仅仅是语法错误?
这不是切换类型的方式。您可以切换对象的实际类型并且必须指定类型名称,而不是 Class
文字。
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");
}
请注意,对于模式匹配,不支持 fall-through,因此必须指定 break
。或者您首先使用没有失败的新语法
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");
}
getType()
返回的对象始终是 java.lang.Class
的实例,因此按其类型进行分支没有意义。这并不意味着无法将实际值与 switch
语句或表达式进行比较。可以使用保护模式执行比较:
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");
}
但这只是为了完整性。我认为很明显,这与 if
语句或从 Class
到处理程序的映射没有任何改进。
作为对方法参数调查的一部分,我尝试了新的 Pattern Matching for switch (Preview)。使用传统条件,它完美地工作:
Method firstMethod = BitSet.class.getDeclaredMethods()[0];
Parameter firstParameter = firstMethod.getParameters()[0];
if (firstParameter.getType() == Integer.class) {
System.out.println("Integer");
}
当我试图重构它以使用 switch
语句时,它没有编译:
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");
}
错误是:
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 ?
这是无法完成的事情,还是仅仅是语法错误?
这不是切换类型的方式。您可以切换对象的实际类型并且必须指定类型名称,而不是 Class
文字。
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");
}
请注意,对于模式匹配,不支持 fall-through,因此必须指定 break
。或者您首先使用没有失败的新语法
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");
}
getType()
返回的对象始终是 java.lang.Class
的实例,因此按其类型进行分支没有意义。这并不意味着无法将实际值与 switch
语句或表达式进行比较。可以使用保护模式执行比较:
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");
}
但这只是为了完整性。我认为很明显,这与 if
语句或从 Class
到处理程序的映射没有任何改进。