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这实际上是不正确的,是什么导致了对这种情况的调查——我最初编写它时也相信这一点。