初学者对象混淆数组

Lin*_*orm 20 java arrays oop polymorphism

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

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

    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

请注意我只是在我的第二个编程课程,所以我的术语可能有点偏.

编辑:问题在这里并没有回答我的问题,因为它没有回答为什么像一个数组的元素x不能援引method2()即使的元素xType 2.我的问题因此而有所不同,因为我的问题也询问为什么第二个错误也会发生时出现第一个错误(为什么一个元素x不能引用该类型的对象Type1并且同时无法调用method2()).我原本以为如果发生一个错误,那么另一个就不会发生.我想比较两个错误和更深入的解释,而不仅仅是多态的规则.

Swe*_*per 15

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

在您的代码中,x在编译时是类型Type1[].这就是编译器认为的那样.在运行时,x是类型Type2[],但编译器不知道.

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

但出现第二个错误在编译时,因为编译器仍然认为x是一个类型的Type1,并没有被调用的方法method2Type1,即使x实际持有一个Type2[]在运行时.

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

((Type2)x[1]).method2();
Run Code Online (Sandbox Code Playgroud)

当天的课程?不要这样做:

Superclass[] array = new Subclass[2];
Run Code Online (Sandbox Code Playgroud)

你会遇到麻烦.


Kra*_*log 6

超类型引用可以指代子类型.我想你明白这一点,因为第一个错误与你有关.

第二个错误源于在编译时x仍然是一个事实Type1[].这意味着在运行时,引用可以包含任何子类型,包括没有该方法的类型method2.这就是为什么你只能使用中定义的方法Type1.

例如,您可以检查该类型是否实际上Type2在运行时使用isInstanceOf,然后将其强制转换为a Type2然后使用method2.但是,通常有更好的解决方案.