【发布时间】:2014-05-20 22:42:46
【问题描述】:
我遇到了一个看似奇怪的问题,尽管我知道这种设计背后可能有一些原因,并且想知道为什么会这样。
考虑两个类,Foo 和 Bar。 Bar 扩展了 Foo 并覆盖了 Foo 实现的方法。 Foo 很简单:
public class Foo {
public Foo() {
System.out.println("Foo constructor");
someMethod();
}
public void someMethod() {
System.out.println("Foo.someMethod");
}
}
酒吧是问题所在。它定义了一个在构造函数之外初始化的数组(我不知道这个术语是什么)。我注意到当从 Foo 调用 someMethod 时,数组还没有被初始化,但是在调用 super() 之后,数组被初始化了。这里是酒吧:
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");
}
}
这不太合理。我想从在超级构造函数中调用的方法访问数组,但数组未初始化。我试图想出一个解决方案。我的第一个想法是在 Bar 的构造函数中初始化数组,但在调用 super 之前仍然不会初始化它。
供参考,输出如下:
Foo constructor
FooBar.someMethod a is null
FooBar constructor
为什么 Java 会这样设计,最好的解决方法是什么?
【问题讨论】:
-
This doesn't quite make sense.你为什么这么认为?当我父亲出生时,我的任何部分都存在吗? -
另外,这个What's wrong with overridable method calls in constructors? 会回答你的大部分问题。
-
除此之外,它只是一个语法糖:数组的初始化发生在
Bar的构造函数中,并且第一次调用必须是超级构造函数。因此,在调用super时,数据尚未初始化 -
就是这样。初始化调用超级构造函数,然后初始化数组,然后调用子构造函数。
-
您实际上可以通过将 a 的 init 移动到子构造函数中来更改它,然后让子构造函数调用
super()数组已初始化。