4

假设有2个班级。并Child延伸Parent.

public class Parent {}

public class Child extends Parent {}

我知道以下代码不正确:

Child obj = new Parent(); // causes java.lang.Error

或者

Child obj = (Child) new Parent(); // causes java.lang.ClassCastException

但是我不明白为什么在第一种情况下会出现编译错误,而在第二种情况下会出现运行时异常。毕竟,父母永远不能转换或转换为孩子。为什么在编译时不检查其中的第二种情况?

我将非常感谢一个清晰合理的想法!

4

4 回答 4

6
Child obj = new Parent();

在这种情况下,编译器会尝试检查(隐式转换)Parent对象是否可以设置为Child引用,并且当此转换失败时,您会收到编译时错误。

Child obj = (Child) new Parent();

在这种情况下,编译器会看到您将Parent对象显式转换为Child,因此编译器将其留给运行时来决定转换是否有效,从某种意义上说,开发人员承担了转换的责任。所以如果这个转换失败,你会得到一个运行时错误。

于 2013-04-28T19:06:17.860 回答
2

孩子 obj = new Parent(); // 导致 java.lang.Error

不,它没有。它会导致编译错误。根本不是一回事。不要通过将不同的事物等同起来来混淆自己。

编译器尽可能多地检查,并将其余的留给运行时。在这种情况下,对 Child 的赋值显然是不正确的,可以在编译时检测到。另一种情况在编译时无法检测到。

于 2013-04-28T22:43:23.870 回答
1

在第二种情况下,您使用显式转换。这意味着基本上你是在告诉编译器你知道会发生什么。这是一种告诉编译器类型是什么的方法,所以他相信你。

然而,运行时必须完成这项工作......他不能,所以他是理所当然地抱怨的人。

(他她?..)

于 2013-04-28T19:06:14.080 回答
1

原因是编译器需要额外的工作来检测这种情况,而且它不能在所有情况下都正确。有时但并非总是将其作为编译器错误是不值得的额外工作。

虽然 Parent 的实例永远不可能是 Child,但对 Parent 的引用实际上可能指向 Child。通常,如果将类型为 Parent的表达式强制转换为 Child,它可能会成功。要确定它不能,编译器必须知道有关 Parent 类型表达式的额外信息。在这种情况下,它是一个构造函数调用。这是最简单的可能情况,并且几乎是唯一一个很明显Parent 类型的表达式不能引用 Child 类型的实例的情况。为了这样最小的好处,向编译器添加额外的复杂性并不值得。

于 2013-04-28T19:09:10.437 回答