【问题标题】:Casting and Inheritance in JavaJava中的强制转换和继承
【发布时间】:2017-06-16 16:08:18
【问题描述】:

考虑一下这个简单的代码:

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 行不应该在运行时不抛出任何异常吗?

【问题讨论】:

  • 请花时间格式化您提供的代码。目前真的,真的很难阅读,没有缩进,一行中有多个语句。请记住,Stack Overflow 的目的是创建一个高质量问题和答案的存储库 - 花时间让您的问题真正高质量。
  • “所以它满足条件 B IS-A A,对吗?”正确的。但是你需要的是“A IS-A B”——但你没有那个。我想混乱来自这里:a1 = a; a = b; // 1 - 通过更改引用 a不会更改 a1。它仍然指向同一个A[]

标签: java inheritance casting


【解决方案1】:

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

因此,您不能将 A 元素的数组转换为 B 元素的数组。

【讨论】:

  • 但是代码编译得很好。它在运行时抛出异常。但是,假设我制作了一个这样的数组:-TestClass c[] = new TestClass[20]。现在,当我尝试b = (B[]) c 时,它给出的提示是不兼容的类型。为什么会有不同的行为?
  • @Shashwat 您可以将 B[] 实例分配给 A[] 变量(就像您可以将 B 实例分配给 A 变量一样)。因此,如果运行时类型匹配,则将 A[] 变量转换为 B[](或将 A 变量转换为 B)可能会在运行时成功。但是,TestClass[] 永远不能转换为 B[],因为 TestClass 不是 B 的子类,而 B 不是 TestClass 的子类。这就是编译器不允许这样做的原因。
  • 让我直说。虽然你不能做到b = (B[]) a1;ba1 是兼容的类型,这就是编译器寻找的全部,所以它编译正确,尽管实际上不可能将b 分配为等于a1。如果我错了,请纠正我。
  • @Shashwat b = (B[]) a1; 可以在运行时成功,如果在此行之前您有一行将B[] 的实例分配给a1(例如a1 = new B[10];)。编译器不分析a1 的运行时类型。它只分析其编译时类型以确定强制转换是否可以在运行时成功。
【解决方案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[],但不能反过来。

【讨论】:

    【解决方案3】:

    你说“B IS-A A”是对的,这就是为什么
    i) 当你输入 a = b; 时没有问题;
    ii) 语句#3 在编译时没有问题

    但你不能说“A IS-A B”,因此运行时异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 2010-11-30
      相关资源
      最近更新 更多