我有两个类parent和child,clascastexception在运行时发生 对于下面给出的代码。
从下面的代码中可以明显看出有classcastexception。 我认为java可以在betterway中处理,因此在下面的情况下它可能会给出编译时错误。
我还有其他原因,java在编译期间没有给出错误。 只是想知道我是否缺少任何东西。
public class ClassCastExcp {
public static void main(String args[]){
Child chd = (Child) new Parent(); //it will force you to cast and gives classcastexception in runtime
}
}
class Parent{
}
class Child extends Parent{
}
答案 0 :(得分:3)
根据您所写的内容,我认为您完全理解为什么会遇到运行时异常。 (如果没有,请参阅其他答案。)
是否有任何原因导致java在编译期间没有出错。只是想知道我是否遗漏了什么。
它没有给出编译错误,因为根据JLS代码是合法的Java。 (有关更多详细信息,请参阅@ ajb的答案,但真正的解释是在JLS本身。)要求兼容的Java编译器接受此...至少在“兼容”模式下。
现在,允许Java编译器 报告类似这样的警告,并且还允许将警告升级为错误。但是:
这个特殊的例子在实际代码中不太可能。编译器编写者通常不会为很少发生的错误实施警告。
任何实施Java编译器的人都会在默认情况下将错误视为 ,这会给那些必须处理其他人/组织编写的代码的用户带来很多抨击。
答案 1 :(得分:2)
JLS 15.3中的这句话很重要:
换句话说,类型为T的表达式的值始终为 适合分配给T类型的变量。
这意味着如果表达式具有类类型T
,那么在运行时,实际值可以是可以分配给类型T
的变量的任何类型,即{{1}或任何子类。
语言规则是基于此编写的。因此,如果你说
T
表达式的类型为(T2)expression
,上面的句子意味着编译器只能假设在运行时表达式可以有类型T
或某个子类。如果表达式可以转换为T
,则演员表是合法的。在您的情况下,由于T2
的某些子类可以转换为Parent
,因此它是合法的。
Child
的情况可能是特例;现在我们知道表达式必须具有类型new Parent()
且不能属于子类类型。但是对于Java来说这是违法的,规则必须重写(语言规范取决于精确规定的规则,因此程序可以在编译器之间移植;编译器实际上不允许使用"常识& #34)。 JLS必须使用"精确类型"或类似的东西来发明表达式的概念,然后需要更改许多其他规则来处理这种表达式。在几个地方添加这种规则需要做很多工作,并验证语言规则中的所有内容是否仍然一致;所有这些工作只会影响病态案例,例如您在实践中从未发生的原始帖子。因此,将Java作为非法行为绝对不值得。
答案 2 :(得分:0)
为简单起见,请参阅下面的代码段
Object x = new Integer(0);
System.out.println((String)x);
现在,println()方法需要String
,因此我们将x
类型的强制转换Object
输入到String
。但是,在运行时Object x
获取Integer
的实例。由于Integer
无法投放到String
。它会在运行时抛出ClassCastException
异常。
现在,回到你的问题,这是一个向下铸造的例子。您不能将父实例存储到子级。请在您的帖子中参考@Axel评论的链接。
答案 3 :(得分:-1)
如果首先完成对象的向上投射然后向下投射,它将不会抛出classcastexception
。
Parent p1=new Child();
Child chd = (Child) p1; // it will not throw classcastexception