DEV*_*DEV 3 java eclipse java-17
我正在使用 Java 17,最后一行不应编译,但是当我使用 eclipse 时它会编译,现在我很困惑该值应该是子类型还是可以是任何东西?
Double value = 123.3;
if(value instanceof Double ) {}
if(value instanceof Double data) {} // DOES NOT COMPILE
Run Code Online (Sandbox Code Playgroud)
该语法是 Java 中相对较新的功能 (JDK 16) 的一部分,他们将其称为模式匹配,并在JEP 394中详细介绍。
如果变量的运行时类型等于其声明的类型,则该示例很简单。所以让我们假设我们有一个
Object value;
Run Code Online (Sandbox Code Playgroud)
其运行时类型恰好是Double.
if (value instanceof Double) {
...
}
Run Code Online (Sandbox Code Playgroud)
这个语句里面如果是aif就会在运行时运行。然而,该变量的编译时类型仍然是,这导致了一个非常常见(且冗余)的范例。valueDoubleObject
if (value instanceof Double) {
Double data = (Double)value; // This cast ALWAYS succeeds
...
}
Run Code Online (Sandbox Code Playgroud)
因为在检查类型之后,我们可能希望使用该变量作为该类型。
所以使用 JEP 394,我们可以写
if (value instanceof Double data) {
...
}
Run Code Online (Sandbox Code Playgroud)
它一次性完成类型检查和转换。最重要的是,该变量立即绑定,并且在后面的连接子句中可用。
if ((value instanceof Double data) && (data.doubleValue() > 0.0)) {
...
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为datais a Double,而不是 an Object。与更详细的预模式匹配语法相反
if ((value instanceof Double) && (((Double)value).doubleValue() > 0.0)) {
...
}
Run Code Online (Sandbox Code Playgroud)
或者
if (value instanceof Double) {
Double data = (Double)value;
if (data.doubleValue() > 0.0) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
在您的特定情况下,由于声明的类型和运行时类型都是Double,因此额外的变量不会给您带来任何好处。这是一种退化的情况,模式匹配语法没有用。但它仍然是允许的。根据编译器的不同,您可能会收到有关此的警告。
JLS-15.20.2明确指出这是不允许的:
\n\n\n如果 RelationalExpression 的类型是 Pattern 类型的子类型,则会发生编译时错误
\n
关于“亚型”的含义,JLS-4.10规定:
\n\n\n类型的超类型是通过直接超类型关系(写作 )上的自反和传递闭包获得的
\nS >1 T,该关系由本节后面给出的规则定义。我们写S :> T是为了表明 S 和 T 之间存在超类型关系。S 是T 的真超类型,写作
\nS > T,如果S :> T并且S \xe2\x89\xa0 T。类型 T 的子类型都是类型 U,因此 T 是 U 的超类型和 null 类型。我们写
\nT <: S是为了表明类型 T 和 S 之间存在子类型关系。T 是S 的真子类型,写作
\nT < S,如果T <: S和S \xe2\x89\xa0 T。
从措辞中可以清楚地看出,类型T必须是其自身的子类型(和超类型)。如果T不能是其自身的子类型(超类型),则无需定义术语“适当的子类型”和“适当的超类型”
该决定的原因记录在JEP-394中:
\n\n\n使模式instanceof表达式将S类型的表达式与T类型的模式进行比较时产生编译时错误,其中S是T的子类型。(此instanceof表达式将始终成功,然后毫无意义。相反的情况,模式匹配总是失败的地方,已经是一个编译时错误。)
\n
请注意(正如 Holger 所指出的)即将推出的 Java 21 版本将取消 RelationalExpression 不能是 Pattern 类型的子类型的要求。这意味着使用 Java 21 您的代码将可以编译。
\n| 归档时间: |
|
| 查看次数: |
280 次 |
| 最近记录: |