当前位置: 首页 > 知识库问答 >
问题:

Java 19模式匹配编译错误:“switch语句没有覆盖所有可能的输入值”

韩淇
2023-03-14

使用Brian Goetz的文章:https://www.infoq.com/articles/data-oriented-programming-java/

sealed interface Opt<T> { 
    record Some<T>(T value) implements Opt<T> { }
    record None<T>() implements Opt<T> { }
}
Opt<String> optValue = doCalc(value);
switch (optValue) {
    case Opt.Some<String>(String s) -> System.out.printf("got string: %s%n", s);
    case Opt.None<String>() -> System.out.printf("got none with value: %d%n", value);
};

使用OpenJDK运行时环境(build 19-ea 27-2074),我得到编译错误:开关语句没有涵盖所有可能的输入值

我可以添加一个默认的case语句,程序就可以运行了。然而,我认为对于密封的记录,给定的switch case将是详尽无遗的,编译器应该认识到默认情况是不必要的。

共有1个答案

赫连法
2023-03-14

JDK 19现在只有早期的Access版本可用。

我想我在JEPS 427留档中找到了这个问题的重要部分

也可以从此处跟踪模式匹配(第三次预览)的进度。

根据下面的JEPS示例,我认为这是可行的,所以我认为您应该先等待第一个JDK 19构建的正式可用性,然后再试一次。如果它仍然不起作用,那么我认为您应该继续并将其作为bug报告。

当允许的直接子类只实现(泛型)密封超类的特定参数化时,需要格外小心。例如:

sealed interface I<T> permits A, B {}
final class A<X> implements I<String> {}
final class B<Y> implements I<Y> {}

static int testGenericSealedExhaustive(I<Integer> i) {
    return switch (i) {
        // Exhaustive as no A case possible!
        case B<Integer> bi -> 42;
    }
}

I的唯一允许子类是A和B,但编译器可以检测到开关块只需要覆盖类B即可详尽无遗,因为选择器表达式是类型I。

我还认为@Kayaman的评论并非如此,因为文档中明确说明了如何安全处理该案件。

为了防止不兼容的单独编译,在切换到一个密封类的情况下,如果开关块是穷举的,并且没有匹配所有的情况,编译器会自动添加一个默认标签,其代码会引发不兼容的ClassChangeError。只有更改密封接口且未重新编译交换机代码时,才能访问此标签。实际上,编译器为您强化了代码。

 类似资料: