【问题标题】:Why does it compile when casting to an unrelated interface? [duplicate]为什么在转换到不相关的接口时会编译? [复制]
【发布时间】:2013-11-18 10:46:47
【问题描述】:
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 是接口时为什么会编译?

【问题讨论】:

    标签: java interface classcastexception


    【解决方案1】:

    编译器不知道这是行不通的:您可以有一个 BlackInk 的子类来实现 Printable。那么演员阵容就好了。

    在编译器知道它不起作用的情况下,你会得到一个错误。

    例如,如果您制作 BlackInk final(这样就不会有子类),您会得到一个错误。

    【讨论】:

    • ...这就是 Gid 发明不安全强制转换警告的原因
    【解决方案2】:

    根据java language specification section: 5.5.1 Reference Type Casting

    对于编译时引用类型S(source) 和编译时引用类型T(target);在将 S 转换为 T 时,如果 Sclass 类型

    • 如果TClass 类型

      1. 那么TS 的子类型 ST 的子类型。否则,会发生编译时错误。
      2. 如果存在T 的超类型XS 的超类型Y,例如 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
        
    • 如果TInterface 类型

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

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

    【讨论】:

      【解决方案3】:

      类型转换发生在run time(记住运行时多态性)。在编译时编译器没有发现代码有任何问题并编译,在运行时它尝试将类型转换 blackinkprintable 并且无法这样做,因为 blackink 没有实现 printable ,因此错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-23
        • 1970-01-01
        • 1970-01-01
        • 2012-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多