日期:2014-05-20  浏览次数:20970 次

有关子类和父类之间转化的问题
interface Foo{}
class A implements Foo{}
class B extends A{}
class C extends B{}

pulbic static void main(String[] args){
  B x = new B();
  //insert code here 


下面哪个选项会引起java.lang.ClassCastException 是?

1) A a = x;
2) Foo f= (C)x;
3) Foo f= (A)x;
4) B b =(B)(A)x;

答案为2),请问各位高人是不是因为类C 没有继承Foo{}接口而引起的错误呀?? 子类转化为父类有没有什么条件呀?本人菜鸟,请多指教!
 

------解决方案--------------------
子类可以强制转换成父类对象。实质上是将对象的地址指针指向了父类对象,对象的内存仍然没变。
你也可以这样理解:子类继承父类,一般会有比父类多的方法 属性,因此子类对象的内存要大于父类。把子类对象转换成父类
,在子类的内存中含有父类的方法属性,因此可以。而把父类转换成子类,在父类的内存中没有子类扩充的方法和属性,因此不可行。
------解决方案--------------------
这是向上造型问题。子类无法转化为比本身还向下的类。但是可以向上造型。

比如Object o = x; 是正确的。


 A x = new B(); Foo x = new B();Object o = new B();是正确的。
但是B x = new A(); 就不正确了。


------解决方案--------------------
你可以用C++的观点来理解这个问题,B b = (B)new A();为什么是不可以的,因为,本身B是子类,他在内存中占的空间是要大于A的,因为毕竟B有一部分属于自己,但是不属于A的东西,如果你强转成功了。那属于A的东西可以被初始化以及实例化,可是属于B的那部分东西是不会被实例化和初始化的,因为A的构造函数是不知道怎么去初始化属于B的东西的。因此,b访问属于B的东西的时候肯定会崩溃。因此java禁止这样做,可是C++是可以的,只不过访问的时候会崩溃。
B b =(B)(A)x;这个为什么是正确的呢。首先看(A)x,因为x是一个B,而B是A的子类,B在内存中的空间大于A,因此(A)x是可行的,此时的(A)x实际是一个B对象,但是他表现的类型是一个A。这就是多态了。(B)(A)x,这个表面上看是把父类对象强转成子类对象,可是内存中不是这样的。因为(A)x,虽然是一个A,但是他在内存中的存储是B,并不是说你吧x搞成了A,原本属于B的那部分空间会被释放(如果是这样,那多态就无从谈起了),所以,(B)(A)x是正确的。不要只看表面,而要看内存分布。