Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的强制转换和继承_Java_Inheritance_Casting - Fatal编程技术网

Java中的强制转换和继承

Java中的强制转换和继承,java,inheritance,casting,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;

考虑以下简单代码:

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,对吗?因此,第3行不应该在运行时抛出任何异常吗

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

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

您说的“B是-A”是正确的,这就是为什么
i) 当你把a=b放进去时,没有问题
ii)语句#3在编译时没有问题


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

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

考虑这一点:

    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[],但不能反过来指定。

请花点时间格式化您提供的代码。现在读起来真的很难,一行没有缩进和多个语句。请记住,堆栈溢出的目的是创建一个高质量问题和答案的存储库-投入时间使您的问题真正具有高质量。“因此它满足条件B is-a,正确吗?”正确。但你需要的是“A是-A是-B”-但你没有。我猜混淆就在这里:
a1=a;a=b;//1
-通过更改参考
a
您没有更改
a1
。它仍然指向相同的
A[]
。但是代码编译得很好。它在运行时抛出异常。但是,假设我创建了这样一个数组:-
TestClass c[]=newtestclass[20]
。现在,当我尝试
b=(b[])c
时,它给出了不兼容的类型。为什么会有不同的行为?@Shashwat您可以将B[]实例分配给a[]变量(就像您可以将B实例分配给a变量一样)。因此,如果运行时类型匹配,则在运行时将A[]变量强制转换为B[](或将A变量强制转换为B)可能会成功。但是,TestClass[]永远不能强制转换为B[],因为TestClass不是B的子类,B也不是TestClass的子类。这就是为什么编译器不允许它。让我直说吧。虽然你不能做
b=(b[])a1
b
a1
是兼容的类型,这是编译器所寻找的所有类型,因此它可以正确编译,尽管实际上不可能将
b
指定为等于
a1
。如果我错了,请纠正我,@Shashwat
b=(b[])a1B[]
的实例分配给
a1
(例如
a1=new B[10];
),则code>可以在运行时成功。编译器不分析
a1
的运行时类型。它只分析其编译时类型,以确定强制转换是否可以在运行时成功。