我实现了这段代码:
class A {
//some code
}
class B extends A {
// some code
}
class C {
public static void main(String []args)
{
B b1 = (B) new A();
A a1 = (B) new A();
}
}
Run Code Online (Sandbox Code Playgroud)
这两行在单独编译时编译正常,但是给出了运行时错误java.lang.ClassException: A cannot be cast into B.
为什么他们编译好,但给出运行时错误?
您需要了解在类型引用下A可以存储任何A扩展的类或类的对象B,就像您的情况一样a.
所以有可能
A a = new B();
Run Code Online (Sandbox Code Playgroud)
由于A引用下的对象是类的实例,a因此应该可以以某种方式将其存储在更准确的引用中,例如B.所以让我们尝试这种方式:
B b = a;//WRONG!!! "Type mismatch" error
Run Code Online (Sandbox Code Playgroud)
这样的代码给我们编译时Type mismatch错误,以防止这种情况:
让我们说
class B1 extends A 和 class B2 extends A 我们创造了A a = new B1();.现在,如果编译器不会抛出B1 b = a;错误,a它也应该允许B1 b = a;但是在其B2 b = a;下面的实例a与之无关B1.
为了告诉编译器我们知道潜在的类型不匹配,我们需要明确地使用强制转换为我们想要的类
B b = (B)a;
Run Code Online (Sandbox Code Playgroud)
这就是为什么在编译时可以引用a类的引用B.
在您的代码中
B b1 = (B) new A();
A a1 = (B) new A();
Run Code Online (Sandbox Code Playgroud)
你需要知道,a运营商返回了创建的对象相同类型的引用,以便B将返回类型的引用(B)a使
B b1 = (B) new A();
Run Code Online (Sandbox Code Playgroud)
实际上是一样的
A tmp = new A();
B b1 = (B) tmp;
Run Code Online (Sandbox Code Playgroud)
这里的问题是你不能存储某个类的对象来引用它的派生类.为什么?如果该派生类具有该对象类不具有的新方法,该怎么办?
class A {
// some code
}
class B extends A {
private int i;
public void setI(int i){
this.i=i;
}
}
Run Code Online (Sandbox Code Playgroud)
之后
B b = (B)new A();
Run Code Online (Sandbox Code Playgroud)
你会试着调用new吗?会有可能吗?不,因为类A的实例没有方法new A(),即使id有,它也没有A在此方法中使用的字段.
这就是b.setI(42);抛出的原因setI.
它在运行时失败的原因是该对象不是B.它是A.所以虽然一些 As可以被转换为B,但是你的不能.
编译器无法分析发生在A对象上的所有事情.例如.
A a1 = new B();
A a2 = new A();
B b1 = (B) a1; // Ok
B b2 = (B) a2; // Fails
Run Code Online (Sandbox Code Playgroud)
所以编译器不确定你的A对象是否实际上可以转换为B.所以在上面,它会认为最后2行是正常的.但是当你真正运行程序时,它意识到这a2不是B,它只是一个A.
| 归档时间: |
|
| 查看次数: |
5758 次 |
| 最近记录: |