最终类的编译器错误实例

时间:2016-01-03 15:22:39

标签: java

以下代码编译良好:

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");
    }

} 

如果我们创建Batfinal,则代码无法编译:

final class Bat { } 

如果最终的类实现了Flyer,那么它编译得很好:

final class Bat implements Flyer { } 

有人想解释这背后的逻辑吗?

3 个答案:

答案 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检查遵循这些规则以进行参考类型转换。