Java 为什么成员对象在超类';谁的构造函数?
昨天我遇到了一个有趣的问题,虽然解决方法很简单,但我对它的“原因”仍然有点模糊 我有一个类,它有一个私有成员变量,当它被实例化时被赋值,但是如果它被用于一个由超类的构造函数调用的抽象函数中,这个变量就没有值。这个问题的解决方案非常简单,我只需将变量声明为静态变量,并正确分配它。一些代码可以说明此问题:Java 为什么成员对象在超类';谁的构造函数?,java,Java,昨天我遇到了一个有趣的问题,虽然解决方法很简单,但我对它的“原因”仍然有点模糊 我有一个类,它有一个私有成员变量,当它被实例化时被赋值,但是如果它被用于一个由超类的构造函数调用的抽象函数中,这个变量就没有值。这个问题的解决方案非常简单,我只需将变量声明为静态变量,并正确分配它。一些代码可以说明此问题: class Foo extends BaseClass { private final String bar = "fooBar!"; public Foo() {
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
@Override
public void initialize()
{
System.out.println(bar);
}
}
以及基类:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
在本例中,当我们调用newfoo()时代码>它将输出(null)而不是预期的fooBar
既然我们实例化了一个Foo类型的对象,那么在调用它(以及它的超类)构造函数之前是否应该分配和分配它的成员呢?这是用Java语言指定的还是特定于JVM的
谢谢你的洞察力 它是由Java语言规范定义的。在现实世界中,将其更改为静态几乎永远都不是一个可接受的解决方案
看到和
总的来说,从构造函数调用非final方法是不好的做法。原因是它可以(如果方法是抽象的,那么肯定会)调用尚未初始化的类中的方法:当执行new Foo()
时,在Foo
构造函数之前调用BaseClass
初始化器(构造函数),因此,Foo.initialize
实际上是在一个尚未完全构造的对象上工作。bar=“fooBar!”的赋值代码>在编译时内联到构造函数中
超类构造器运行子类构造器,因此随后执行语句是很自然的
不过,一般来说,从构造函数调用可重写的方法是很困难的 小心从超类ctor调用子类方法。代码实际上会打印fooBar!因为bar
变量是final,这使得它成为编译时常量。如果没有final
,它将打印空。@x22这实际上是不正确的,是什么导致了对这种情况的调查——我最初编写它时也相信这一点。