初学者对象数组混淆

2022-09-02 10:22:02

我无法理解在以下代码中声明数组时实际发生的情况。

class Type1 {

}

class Type2 extends Type1 {
    public void method2() {

    }
}

class Test {
    public static void main(String[] args) {

        Type1[] x = new Type2[2];
        x[0] = new Type1(); // runtime error
        x[1] = new Type2();
        x[1].method2(); // syntax error

    }
}

我认为由于数组声明的右侧是数组将由该类型的参考变量组成。如果这是真的,那么第一个错误是有意义的,因为我不能有一个子类型引用超类型。new Type2[2]Type2

但是,为什么第二个错误发生在两行之后?Type2 不知道,所以引用变量知道该方法?这似乎是因为不知道,所以这是否意味着数组由该类型的参考变量组成?如果这是真的,为什么会发生第一个错误,因为它不再是引用超类型的子类型?method2()Type1method2Type1

另外,为什么第一个错误是运行时错误,而另一个错误是语法错误?

请注意,我只是在第二门编程课程中,所以我的术语可能有点偏差。

编辑:这里的问题没有回答我的问题,因为它没有回答为什么数组中的元素不能调用,即使.我的问题与此不同,因为我的问题还询问为什么在第二个错误也发生时会发生第一个错误(为什么的元素不能引用和该类型的对象,同时不能调用)。我最初认为,如果发生一个错误,那么另一个错误就不会发生。我想要比较这两个错误,并给出一个更深入的解释,而不仅仅是多态性规则。xmethod2()xType 2xType1method2()


答案 1

这是Java允许你做的那些奇怪的事情之一,将派生类的数组分配给基类的数组的变量。

在您的代码中,在编译时是 类型 。这就是编译器所认为的。在运行时,是 类型,但编译器不知道。xType1[]xType2[]

第一个错误发生在运行时,因为如您所说,您无法分配给 类型的变量。Type1Type2

但是第二个错误发生在编译时,因为编译器仍然认为这是类型,并且没有调用的方法,即使实际上在运行时持有。xType1method2Type1xType2[]

要调用 ,您需要通过强制转换来告诉编译器类型:method2x[1]Type2

((Type2)x[1]).method2();

当天的课程?别这样:

Superclass[] array = new Subclass[2];

你会给自己带来麻烦。


答案 2

超类型引用可以引用子类型。我想你明白这一点,因为第一个错误对你来说是连贯的。

第二个错误源于这样一个事实,即在编译时,仍然是一个.这意味着在运行时,引用可以保存任何子类型,包括不具有方法的类型。因此,您只能使用 中定义的方法。xType1[]method2Type1

例如,您可以检查该类型是否实际上是在运行时 using ,然后将其转换为 a,然后使用 。不过,通常有更好的解决方案。Type2isInstanceOfType2method2