cla*_*lay 10 java pattern-matching switch-statement
使用 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> { }
}
Run Code Online (Sandbox Code Playgroud)
这将按预期编译并运行。详尽的模式匹配工作原理:
Opt<String> optValue = doCalc(value);
switch (optValue) {
case Opt.Some<String> some -> System.out.printf("got string: %s%n", some.value());
case Opt.None<String> none -> System.out.printf("got none%n");
};
Run Code Online (Sandbox Code Playgroud)
我使用新的记录模式预览功能的这种变体打破了详尽的模式匹配,如果不添加默认的 case 语句,则无法编译:
Opt<String> optValue = doCalc(value);
switch (optValue) {
case Opt.Some<String>(String v) -> System.out.printf("got string: %s%n", v);
case Opt.None<String> none -> System.out.printf("got none%n");
};
Run Code Online (Sandbox Code Playgroud)
使用OpenJDK Runtime Environment (build 19-ea+32-2220),我得到编译错误:the switch statement does not cover all possible input values。
当我添加默认的 case 语句时,程序可以工作,但我没有得到详尽的模式匹配。
如果我删除记录模式匹配,程序就可以工作。
如果我创建一个不带泛型的变体,使用密封类、详尽的模式匹配和记录模式,它就可以工作。
然而,记录模式、泛型和详尽模式匹配的组合似乎不起作用。
JDK 19现在仅提供早期访问版本。
我想我已经在这个问题中找到了重要的部分我想我已经在JEPS 427 文档
模式匹配(第三次预览)的进度也可以从也可以从这里。
根据下面的 JEPS 示例,我希望这能起作用,所以我认为您应该首先等待第一个JDK 19 版本的普遍可用性,然后重试。如果它仍然不起作用,那么我认为你应该继续并将其报告为错误。
当允许的直接子类仅实现(通用)密封超类的特定参数化时,需要额外小心。例如:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
I 唯一允许的子类是 A 和 B,但编译器可以检测到 switch 块只需要覆盖类 B 即可穷举,因为选择器表达式是类型 I。
我也认为@Kayaman的评论不是这种情况,因为文档中明确说明了如何处理这种情况才能安全。
为了防止不兼容的单独编译,在切换密封类的情况下,其中 switch 块是详尽的并且不存在全部匹配的情况,编译器会自动添加一个默认标签,其代码会抛出 IncompleteClassChangeError。只有改变密封接口并且不重新编译开关代码时才会到达该标签。实际上,编译器会为您强化代码。