下面的代码可以正常编译:
interface Flyer{ }
class Bat { }
public class App {
public static void main(String[] args) {
Bat b = new Bat();
if(b instanceof Flyer) System.out.println("b is a Bird");
}
}
如果我们将 Bat
类设为 final
,则代码无法编译:
final class Bat { }
如果最终类实现了 Flyer
,它编译得很好:
final class Bat implements Flyer { }
有人愿意解释这背后的逻辑吗?
当你上课时 Bat
final
,你是说这个类不能被子类化。自 Bat
没有实现接口(interface) Flyer
,编译器能够确定 b instanceof Flyer
永远不可能是true
并引发错误。
这是在 JLS section 15.20.2 中指定的:
If a cast (§15.16) of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof
relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof
expression could never be true.
此外,来自 section 15.16关于转换表达式:
It is a compile-time error if the compile-time type of the operand may never be cast to the type specified by the cast operator according to the rules of casting conversion (§5.5).
在这种情况下,Bat
永远不能转换为 Flyer
: 它没有实现它并且final
确保不会有子类来实现它。
正如您所发现的,修复是:
- 制作
Bat
实现 Flyer
:在这种情况下,instanceof
运算符总是返回 true
.
- 删除
final
标识符,暗示可能有 Bat
的子类实现 Flyer
.