是否可以将 Class<?> 与新的模式匹配开关一起使用?

问题描述 投票:0回答:1

作为方法参数调查的一部分,我尝试了新的开关模式匹配(预览)。使用传统条件,效果完美:

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 ?

这是无法完成的事情,还是只是语法错误?

java switch-statement java-17 preview-feature
1个回答
8
投票

这不是类型切换的工作原理。您可以切换对象的实际类型,并且必须指定类型名称,而不是

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");
}

请注意,对于模式匹配,没有失败支持,因此必须指定

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 when cl == Integer.class -> System.out.println("Integer");
    case Class<?> cl when cl == int.class -> System.out.println("int");
    case Class<?> cl when cl == String.class -> System.out.println("String");
    case Class<?> cl when cl == long.class -> System.out.println("long");
    case Class<?> cl when BitSet.class.isAssignableFrom(cl)
                                  -> System.out.println("BitSet or subtype");
    default -> System.out.println("other");
}

请注意,JDK 17 预览版使用

&&
而不是
when

但这只是为了完整性。我认为很明显,这比

if
语句或从
Class
到处理程序的映射没有任何改进。

© www.soinside.com 2019 - 2024. All rights reserved.