Java Casting接口到类

kom*_*nan 18 java casting

public class InterfaceCasting {

    private static class A{}

    public static void main(String[] args) {
        A a = new A();
        Serializable serializable = new Serializable(){};
        a = (A)serializable;
    }

}
Run Code Online (Sandbox Code Playgroud)

编译成功但运行时异常

Exception in thread "main" java.lang.ClassCastException: InterfaceCasting$1 cannot be cast to InterfaceCasting$A
Run Code Online (Sandbox Code Playgroud)

为什么汇编成功?编译器必须知道serialiazable不是A?

aio*_*obe 29

正如你所指出的,这编译:

interface MyInterface {}

class A {}

public class InterfaceCasting {
    public static void main(String[] args) {
        MyInterface myObject = new MyInterface() {};
        A a = (A) myObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,不会编译:

interface MyInterface {}

class A {}

public class InterfaceCasting {
    public static void main(String[] args) {
        A a = (A) new MyInterface() {}; // javac says: "inconvertible types!"
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,这里发生了什么?有什么不同?

那么,既然MyInterface是一个简单的界面,可以很好地通过扩展一个类来实现,在这种情况下,从铸造MyInterfaceA会是合法的.


例如,这段代码将在50%的所有执行中成功,并说明编译器需要解决可能不可判定的问题,以便在编译时始终"检测"非法转换.

interface MyInterface {}

class A {}

class B extends A implements MyInterface {}

public class InterfaceCasting {
    public static void main(String[] args) {
        MyInterface myObject = new MyInterface() {};
        if (java.lang.Math.random() > 0.5)
            myObject = new B();
        A a = (A) myObject;
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*s_D 9

Java语言规范声明:

在编译时可以证明某些演员阵容不正确; 这样的强制转换会导致编译时错误.

后来在节目中将编译时参考类型S的值转换为编译时参考类型T的编译时合法性的详细规则 - 当心,它们非常复杂且难以理解.

有趣的规则是:

  • 如果S接口类型:
    • 如果T是一个非final的类型(§8.1.1),那么如果存在T的超类型X和S的超类型Y,那么X和Y都可以证明是不同的参数化类型,并且X和Y相同,发生编译时错误.否则,强制转换在编译时总是合法的(因为即使T没有实现S,也可能是T的子类).

在你的例子中,非常清楚,演员表是非法的.但请考虑这个微小的变化:

public class InterfaceCasting {

    private static class A{}
    private static class B extends A implements Serializable{}

    public static void main(String[] args) {
        A a = new A();
        Serializable serializable = new B(){};
        a = (A)serializable;
    }    
}
Run Code Online (Sandbox Code Playgroud)

现在可以在运行时从一个Serializableto A转换,这表明,在这些情况下,最好留给运行时来决定我们是否可以强制转换.


卢声远*_* Lu -1

Serializable不是 an A,所以它会抛出ClassCastException