请告诉我为什么我在这种情况下得到ClassCastException
我有类型转换,B类的来源如下所示,但为什么我仍然在这里得到ClassCastException。
public class A extends B
{
}
public class B {
public String getData() {
return "B";
}
}
public class Main {
public static void main(String args[]) {
A a = new A();
B b = new B();
a = (A) b;
System.out.println(a.getData());
}
}
答案 0 :(得分:2)
如果我们使用不同的类名,那就更明显了:
public class Car extends SomethingWithWheels {} // was A extends B
public class SomethingWithWheels {} // was B
public class Train extends SomethingWithWheels {} // aahh, some C extends B
现在,让我们再次投射:
SomethingWithWheels somethingWithWheels = getItFromSomewhere();
Car car = (Car) somethingWithWheels;
编译器必须抱怨,因为somethingWithWheels
(B
)可能是Train
实例(C
),无法转换为Car
}(A
)。
答案 1 :(得分:0)
因为B
的实例不是 A
的实例。这真的很简单。
如果您创建A
的实例,它也是B
- 因为这就是子类化的含义。但是,如果您创建B
的实例,那就是不 A
,并且不能像这样分配/转换。
您可以投射的唯一时间是对象的运行时类是否与您尝试强制转换的类型兼容。你不能更改现有对象的类 - 这是我认为你可能在这里尝试做的 - 只告诉编译器“看,我知道它真的更具体”。
作为反例,以下内容可行:
public static void main(String args[]) {
B b = new A();
A a = (A) b;
System.out.println(a.getData());
}
在这种情况下,变量b
被声明为保存对B
的引用。事实证明,您使用A
的实例填充它,但对于程序的其余部分,编译器不允许假设b
是A
,因为它不能保证。由于您知道在您的特定情况下是A
,因此您插入强制转换,这会导致运行时检查对象实际上是A
。这样就可以了,从那时起,您可以在A
变量上调用特定于a
的方法。
在这种情况下,根本没有理由进行任何转换 - 在您需要调用的子类上没有可用的额外方法,并且没有只采用A
而不是{a} {}的方法B
。即使A
覆盖getData
做了不同的事情,如果通过B
引用进行调用,您仍会遇到此行为。
答案 2 :(得分:0)
您无法将基类强制转换为派生类。你可以反过来做。
答案 3 :(得分:0)
因为您的实例“b”不是A类型(B不扩展A),所以当您将“b”转换为A时它会失败。 相反的方法是有效的(将类型A的实例转换为类型B)
答案 4 :(得分:0)
您正在向下转换并尝试将超类型转换为子类型,这就是为什么它在编译期间表现良好但在运行时因ClassCastException而失败。
您可以致电:
System.out.println(a.getData());
删除尝试转换类型的行