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

时间:2013-11-06 23:20:15

标签: 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;
    }
}

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

3 个答案:

答案 0 :(得分:17)

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

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

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

答案 1 :(得分:12)

根据java language specification section: 5.5.1 Reference Type Casting

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

  • 如果T类型为Class

    1. 然后T是[{1}} 的子类型或 SS的子类型。否则,将发生编译时错误。
    2. 如果存在T的超级X,以及T的超级类型Y,则为 SX都可以证明是不同的参数化类型 YX的删除相同,发生编译时错误

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

    1. 如果Interface不是S类,那么,如果存在final的超级X,则 T的超类型Y,以便SX可证明是不同的参数化 类型,YX的删除相同,发生编译时错误。 否则,演员在编译时总是合法的(因为即使Y没有 实现ST的子类可能
    2. 如果S是最终类,则S必须实现T或编译时错误 发生。

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

答案 2 :(得分:1)

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