为什么在转换为不相关的接口时会编译?

interface Printable {} class BlackInk {} public class Main { public static void main(String args[]) { Printable printable = null; BlackInk blackInk = new BlackInk(); printable = (Printable)blackInk; } } 

如果编译并运行前面的代码,则结果是printable = (Printable)blackInk;的ClassCastException printable = (Printable)blackInk; 。 但是,如果将Printable更改为类,则不会编译,因为blackInk无法强制转换为Printable。 当Printable是一个接口时,为什么要编译?

编译器不知道这不起作用:你可以有一个实现Printable的BlackInk子类。 然后演员会很好。

在编译器知道它不起作用的情况下,您将收到错误。

例如,如果你使BlackInk成为final (这样就没有子类)就会出错。

根据java语言规范部分:5.5.1 引用类型转换

对于编译时引用类型S (源)和编译类型引用类型T (目标); 在将转换从S转换为T如果Sclass Type

  • 如果TClass类型

    1. 那么TS的子类型 ST的子类型。 否则,发生编译时错误。
    2. 如果存在T的超类型XS的超类型Y ,使得XY都可certificate是不同的参数化类型,并且XY的擦除相同,则发生编译时错误

       class S{} class T extends S{} //// S s = new S(); T t = (T)s; // run time ClassCastException will happen but no compile time error 
  • 如果TInterface类型

    1. 如果S不是final类,那么,如果存在T的超类型XS的超类型Y ,使得XY都可certificate是不同的参数化类型,并且XY的擦除是相同的,发生编译时错误 。 否则,强制转换在编译时总是合法的( 因为即使S没有实现TS的子类也可能
    2. 如果S是最终类,那么S必须实现T,否则会发生编译时错误。

这适用于您的情况,即使在编译时检测到类转换,也会在runtime检测到接口转换。

类型转换在run time发生(记住运行时多态)。 在编译时编译器没有看到代码和编译有任何问题,并且在运行时它尝试将cast blackink键入printable ,并且无法执行此操作因为blackink不实现printable ,因此错误。