Java中的转换和继承

时间:2017-01-31 09:29:18

标签: java inheritance casting

考虑这个简单的代码:

class A {}

class B extends A {}

public class TestClass {
    public static void main(String args[]) {
        A[] a, a1;
        B[] b;
        a = new A[10];
        a1 = a;
        b = new B[20];
        a = b; // 1
        b = (B[]) a; // 2
        b = (B[]) a1; // 3
    }
}

仔细查看我评论1,2和3的行。编译期间将允许第1行,因为赋值是从子类引用到超类引用完成的。

第2行中的强制转换是必需的,因为超类引用被分配给子类引用变量。这在运行时工作,因为a引用的对象实际上是B(第1行)的数组。

现在,这就是我的困惑所在:第3行将抛出java.lang.ClassCastException。现在,这意味着在运行时,程序意识到实际对象不是B的数组,而是A的数组。

这正是我不明白的地方。 B不延伸A吗?所以它满足条件B IS-A A,对吗?因此,第3行不应该在运行时抛出任何异常吗?

3 个答案:

答案 0 :(得分:7)

a1是一个A元素数组。自B扩展A以来,B的所有实例都是A的实例,但A的所有实例都不是B的实例。您可以定义一个类C,它还扩展A并将该类的实例分配给a1数组。此类实例不是B的实例。

因此,您无法将A元素数组转换为B元素数组。

答案 1 :(得分:2)

你忘记了,数组本身就是类,它们有自己的转换和赋值规则。

考虑一下:

    A[] aa = new A[0];
    B[] bb = new B[0];

    System.out.println(aa.getClass());
    System.out.println(bb.getClass());

    System.out.println(aa.getClass().isAssignableFrom(bb.getClass()));
    System.out.println(bb.getClass().isAssignableFrom(aa.getClass()));

输出:

class [Lstuff.small.Try47$A;
class [Lstuff.small.Try47$B;
true
false

因此,A []变量确实可以被赋予B [],但不是相反。

答案 2 :(得分:0)

你说对了#34; B IS-A A"这就是为什么
  i)当你输入a = b时没有问题;
  ii)语句#3

在编译时没有问题

但你不能说"一个IS-A B",因此是运行时例外。