以下代码编译良好:
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 { }
有人想解释这背后的逻辑吗?
答案 0 :(得分:6)
当你上课Bat
final
时,你说这个班级不能被分类。由于Bat
未实现接口Flyer
,因此编译器能够确定b instanceof Flyer
永远不会true
并引发错误。
这在JLS section 15.20.2中指定:
如果 RelationalExpression 对 ReferenceType 的强制转换(第15.16节)将作为编译时错误被拒绝,那么
instanceof
关系表达式同样如此产生编译时错误。在这种情况下,instanceof
表达式的结果永远不会成立。
此外,从section 15.16关于强制转换表达式:
如果操作数的编译时类型永远不会根据强制转换规则(第5.5节)强制转换为强制转换运算符指定的类型,那么这是一个编译时错误。
在这种情况下,永远不能将Bat
强制转换为Flyer
:它不实现它,final
确保不存在实现它的子类。
正如您所发现的,修复方法是:
Bat
实施Flyer
:在这种情况下,instanceof
运算符将始终返回true
。final
标识符,暗示可能存在Bat
实施Flyer
的子类。答案 1 :(得分:4)
好吧,如果Bat
是最终类并且它没有实现Flyer
,那么它也不能有任何实现Flyer
的子类,所以{{1永远不会返回true。在这种情况下,编译器不允许使用此表达式(即只有instanceof
包含对实现或扩展(x instanceof Y)
的实例的引用的机会时才允许x
。 / p>
在您的第二个代码段Y
已经实施Bat
,因此无论Flyer
是否为最终,b instanceof Flyer
始终会返回true
。
答案 2 :(得分:4)
除了来自JLS的@Tinaki的引用之外,https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.5.1中也明确解释了这一点,引用相关规则:
如果S是
if($_POST['bool'] == 1) { $bool = "b'1'"; } else { $bool = "b'0'"; } $statement = $pdo->prepare("INSERT INTO `test` (SomeText,TestBool) VALUES (?,$bool)") ; $statement->execute(array("TEST")) ;
类(第8.1.1节),则S必须实现T,否则会发生编译时错误。
final
检查遵循这些规则以进行参考类型转换。