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是一个接口时,为什么要编译?
答案 0 :(得分:17)
编译器不知道这不起作用:你可以有一个实现Printable的BlackInk子类。然后演员会很好。
在编译器知道它不起作用的情况下,您将收到错误。
例如,如果你制作BlackInk final
(这样就没有子类)就会出错。
答案 1 :(得分:12)
根据java language specification section: 5.5.1 Reference Type Casting:
对于编译时引用类型S
(源)和编译类型引用类型T
(目标);在转换从S
转换为T
时,如果S
是class
类型
如果T
类型为Class
:
T
是[{1}} 的子类型或 S
是S
的子类型。否则,将发生编译时错误。如果存在T
的超级X
,以及T
的超级类型Y
,则为
S
和X
都可以证明是不同的参数化类型
Y
和X
的删除相同,发生编译时错误。
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
:
Interface
不是S
类,那么,如果存在final
的超级X
,则
T
的超类型Y
,以便S
和X
可证明是不同的参数化
类型,Y
和X
的删除相同,发生编译时错误。
否则,演员在编译时总是合法的(因为即使Y
没有
实现S
,T
的子类可能)这适用于您的情况,即使在编译时检测到类转换,也会在S
中检测到接口转换。
答案 2 :(得分:1)
类型转换发生在run time
(记住运行时多态)。在编译时,编译器没有看到代码和编译有任何问题,并且在运行时它尝试将强制转换blackink
键入printable
,但由于blackink
没有,因此无法执行此操作实现printable
,因此错误。