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

kor*_*doo 8 java interface classcastexception

interface Printable {}
class BlackInk {}

public class Main {
    public static void main(String args[]) {
        Printable printable = null;
        BlackInk blackInk = new BlackInk();
        printable = (Printable)blackInk;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Thi*_*ilo 17

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

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

例如,如果你制作BlackInk final(这样就没有子类)就会出错.


Sag*_*age 13

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

对于编译时引用类型S(源)和编译类型引用类型T(目标); 在转换为Sto时T,If S是一个classType

  • 如果T是一个Class类型:

    1. 然后要么T是子类型,S 要么 S是子类型T.否则,发生编译时错误.
    2. 如果存在一个超型XT,和超类型YS,使得两个XY是可证明不同参数化类型,那的擦除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
      
      Run Code Online (Sandbox Code Playgroud)
  • 如果TInterface类型:

    1. 如果S不是final类,然后,如果存在的超类型XT,和超类型YS,使得两个XY是可证明不同参数化类型,那的擦除XY是相同的,一个编译时错误发生.否则,强制转换在编译时总是合法的(因为即使S没有实现T,S也可能是子类)
    2. 如果S是最终类,那么S必须实现T,否则会发生编译时错误.

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