Java 为什么ClassCastException是一个运行时错误?

Java 为什么ClassCastException是一个运行时错误?,java,types,Java,Types,正在尝试以下操作: class Base { public Base(){ } } class Derived extends Base { } public class Main { public static void main (String[] args) { Derived derived = (Derived) new Base(); } } 导致CastClassException,但编译成功。上的注释表明,编译器在运行

正在尝试以下操作:

class Base {
    public Base(){
    }
}

class Derived extends Base {
}

public class Main
{
    public static void main (String[] args)
    {
        Derived derived = (Derived) new Base();
    }
}
导致
CastClassException
,但编译成功。上的注释表明,编译器在运行时之前不可能找出
newbase()
的类型,但为什么会这样呢?我知道,在编译器中,总是可以推断出任何表达式的类型,Java编译器肯定会对lambda表达式等进行一些类型推断。它必须在某个时刻知道
newbase()
的类型,才能发出正确的字节码

是否存在理论上的限制,阻止Java编译器在程序运行之前捕捉到这一点,或者这是一种实现选择

public static void main(String[] args) throws Exception {
    Derived derived = (Derived) getObject();
}

public static Base getObject() {
    if (Math.random() > 0.5) {
        return new Base();
    } else {
        return new Derived();
    }
}

现在怎么办?编译器如何知道?编译器(主要)限于静态信息。对象的类型是动态信息。

新基(的结果是一个
,在任何其他上下文中都可以是
派生的。
编译器不会传播特殊知识,在这种情况下,它实际上是
基。

是否存在理论上的限制,阻止Java编译器在程序运行之前捕捉到这一点,或者这是一种实现选择

public static void main(String[] args) throws Exception {
    Derived derived = (Derived) getObject();
}

public static Base getObject() {
    if (Math.random() > 0.5) {
        return new Base();
    } else {
        return new Derived();
    }
}

不做特例是一种实现选择。

任何允许子类化的语言的合理实现都有可能出现强制转换异常(或其等价物)

子类化方案的强大之处在于,您可以拥有在泛型超类上操作的方法,而不必知道特定的子类。但是迟早会需要执行特定于子类的操作,为此必须将引用转换为子类。如果该转换是错误的,因为您误解了对象的实际类,那么逻辑上应该发生转换异常


您可能可以将强制转换异常隐藏在某种机制后面,例如,如果对象的类型不正确,则该机制将返回NULL,但这只是将一个异常替换为另一个异常。

因为它发生在运行时??强制转换告诉编译器忽略它自己的类型信息,而是信任程序员。这就是为什么它没有抓住这个。编译器说,“我知道这是类型base,但程序员说它是派生的。他们最清楚。”我没有想到这样的情况。对我来说,拒绝模棱两可的案例似乎更为明智——是否有充分的理由编写一个50%失败的cast?但我明白为什么,我想。@patrick铸造通常不被认为是良好的实践。我的示例旨在说明编译器所能知道的是有限的。语言设计者一定决定不使用特殊情况处理。是的,我喜欢C#如何使用
as