简体   繁体   English

直到调用超级构造函数之后,在声明中初始化的数组才实际初始化

[英]Array initialized at declaration not actually initialized until after call to super constructor

I am experiencing a seemingly odd problem, although I understand there is probably some reason behind this design, and would like to find out why it is this way. 我遇到了一个看似奇怪的问题,尽管我知道该设计背后可能存在某些原因,并且想找出原因。

Consider two classes, Foo and Bar. 考虑两个类,Foo和Bar。 Bar extends Foo and overrides a method that Foo implements. Bar扩展了Foo并覆盖了Foo实现的方法。 Foo is quite simple: Foo很简单:

public class Foo {
    public Foo() {
        System.out.println("Foo constructor");
        someMethod();
    }

    public void someMethod() {
        System.out.println("Foo.someMethod");
    }
}

Bar is where the problem is. 酒吧是问题所在。 It defines an array which is initialized outside the constructor (I don't know what the term is for this). 它定义了一个在构造函数外部初始化的数组(我不知道这个术语是什么)。 I noticed that when someMethod is called from Foo, the array has not yet been initialized, but when right after the call to super(), the array IS initialized. 我注意到当从Foo调用someMethod时,该数组尚未初始化,但是在调用super()之后立即对数组进行了初始化。 Here is Bar: 这是酒吧:

public class Bar extends Foo {
    int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    public Bar() {
        super();
        System.out.println("FooBar constructor");
        if (a == null) System.out.println("FooBar a is null");
    }

    public void someMethod() {
        if (a == null) System.out.println("FooBar.someMethod a is null");
    }
}

This doesn't quite make sense. 这不太有意义。 I want to access the array from a method which is called in the super constructor, but the array isn't initialized. 我想从在超级构造函数中调用的方法访问数组,但是该数组未初始化。 I have tried to think of a solution. 我试图思考一个解决方案。 My first idea was to initialize the array in Bar's constructor, but that still won't initialize it before the call to super. 我的第一个想法是在Bar的构造函数中初始化数组,但是在调用super之前仍然不会初始化数组。

For reference, the output is as follows: 供参考,输出如下:

Foo constructor
FooBar.someMethod a is null
FooBar constructor

Why is Java designed like this, and what is the best way around it? 为什么Java是这样设计的?围绕它的最佳方法是什么?

The superclass constructor must finish successfully before the rest of the subclass constructor begins. 在其余子类构造函数开始之前,超类构造函数必须成功完成。 Only then will subclass variables be initialized, so during the superclass constructor, a in Bar is still null . 只有这样,子类变量初始化,所以父类的构造过程中, aBar仍然是null This curious situation arises because a method called by a superclass constructor is overridden in the subclass, so a subclass method is called before the subclass is itself initialized. 之所以出现这种奇怪的情况,是因为在子类中重写了由超类构造函数调用的方法,因此在子类自身初始化之前先调用子类方法。

For more info on why it's bad Java leaking this in constructor . 有关Java为何如此糟糕的更多信息,请在构造函数中泄漏此信息 This lets an object that is not fully initialized be accessible to other objects. 这使未完全初始化的对象可被其他对象访问。

The best thing to do here is not to have the superclass constructor call a method that gets overridden in a subclass. 最好的做法是不要让超类构造函数调用在子类中被重写的方法。 Let Bar do its own initialization/manipulation of a if it would like. Bar做自己的初始化/操纵a ,如果它想。

The constructor for the superclass must complete before anything is done in the subclass constructor. 在子类构造函数中完成任何操作之前,超类的构造函数必须完成。 This will include any initialization. 这将包括任何初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM