【发布时间】:2022-11-24 04:46:53
【问题描述】:
在 Java 19 中,我试图在 assert 语句中使用 instanceof 模式匹配。
我希望匹配的类型在语句之后可用,但 Java 编译器不识别新变量。
我们创建了一个变量Object obj,我们无法知道它包含Integer还是String。
我们将变量传递给两个测试方法。
public class AssertPatternMatching {
public static void main(String[] args) {
Object obj = args.length == 0 ? Integer.valueOf(42) : "Hello";
afterAssert(obj);
insideMessage(obj);
}
在方法afterAssert()中,我们断言obj是一个String,并通过instanceof模式匹配将字符串绑定到新变量str。
我希望 str 在下一行中被知道和使用。
但是,编译器不知道符号str。
private static void afterAssert(Object obj) {
assert obj instanceof String str;
str.length(); // javac: cannot find symbol variable str
}
在方法insideMessage()中,我们使用复杂的assert语句来检查obj是不是String。如果是,则断言失败,我们可以提供一条消息。
由于 instanceof 检查被否定,模式匹配 str 变量应该可用于错误消息。
然而,编译器还是不知道符号str。
private static void insideMessage(Object obj) {
assert !(obj instanceof String str) : "Is a string: " + str.length();
// line above: javac: cannot find symbol variable str
obj.hashCode();
}
如果我们将 assert 语句替换为 if,它就会起作用:
private static void afterAssertIf(Object obj) {
if(obj instanceof String str) {
str.length();
} else {
throw new AssertionError();
}
}
private static void insideMessageIf(Object obj) {
if (!(obj instanceof String str)) {
obj.hashCode();
} else {
throw new AssertionError("Is a string: "+ str.length());
}
}
这内部消息()example 确实是一个边缘案例,所以我知道它不受支持。 我本来以为后断言()但是,要工作。 这是故意的设计选择还是错误? 如果是故意的,理由是什么?
完整代码在https://gist.github.com/enikao/57bb1b10ce3126494ec4baa2bc7db2df
【问题讨论】:
标签: java pattern-matching assert instanceof