如何从超类构造函数

时间:2017-09-08 12:59:11

标签: java inheritance memory-management

我有一个类,其中超类在构造函数中读取一个巨大的对象(大量解析)来初始化它的值。在子类中,我需要来自该巨大对象的第二个值。我不想两次解析文件,并且我不想在内存中保留解析结果,因为它不再需要。

我想做的事情看起来像这样(在Java中不可能):

public class Superclass {
    private Object foo;

    public Superclass() {
        HugeObject huge = getHugeObject();
        this.foo = huge.getFoo();
        return huge; // “huge” gets garbage collected if not used
    }
}

public class Subclass extends Superclass {
    private Object bar;

    public Subclass() {
        HugeObject huge = super();
        this.bar = huge.getBar(); // “huge” gets garbage collected, too
    }
}

我可以编写什么,但如果直接使用Superclass,则不会删除huge,只要超类对象正在使用,它就会保留在内存中:

public class Superclass {
    protected HugeObject huge; // to pass the huge object to subclass
    private Object foo;

    public Superclass() {
        this.huge = getHugeObject();
        this.foo = this.huge.getFoo();
        // this.huge = null; // “huge” NOT garbage collected (would cause NPE in Subclass)
    }
}

public class Subclass extends Superclass {
    private Object bar;

    public Subclass() {
        this.bar = super.huge.getBar();
        super.huge = null; // “huge” gets garbage collected only when Subclass used
    }
}

事实上,这个问题似乎与OO编程一般都是违反直觉的。我可以在huge = null;的任何方法中编写Superclass,因此该对象将被提前删除,但这也不像是好的风格。是否有更多Java / OO方法可以更好地解决这个问题?是否有类似“post构造函数”的东西可以在所有子类的构造函数运行后执行?像

这样的东西
public Superclass() {
    this.huge = getHugeObject();
    this.foo = this.huge.getFoo();
} finally /* executes after subclass constructor has finished */ {
    this.huge = null;
}

也许使用回调?

2 个答案:

答案 0 :(得分:0)

我可能会使用一种回调。

public class Superclass {
    private Object foo;

    public Superclass() {
        HugeObject huge = getHugeObject();
        gotHugeObject(huge);
    }

    /*
     * NB: Called during construction! Beware of leaking `this` etc.!!!
     */
    protected void gotHugeObject(HugeObject huge) {
        this.foo = huge.getFoo();
    }
}

public class Subclass extends Superclass {
    private Object bar;

    /*
     * NB: Called during construction! Beware of leaking `this` etc.!!!
     */
    @Override
    protected void gotHugeObject(HugeObject huge) {
        super.gotHugeObject(huge);
        this.bar = huge.getBar(); // “huge” gets garbage collected, too

    }
}

这样做有一些警告。主要是,此时对象正处于构造过程中,因此存在泄漏this的危险,这可能导致模糊的问题。

然而,由于简单明了发生了什么,你可以通过评论来缓解问题,所以对我来说这将是最明智的选择。

答案 1 :(得分:-1)

如果要将它重用于多个实例,那么最好将HugeObject传递给构造函数:

public Superclass(HugeObject huge) {
        this.huge = huge;
        this.foo = this.huge.getFoo();
        // this.huge = null; // “huge” NOT garbage collected (would cause NPE in Subclass)
    }

现在您可以控制HugeObject生命周期

HugeObject huge = /* initiate */;
new SuperClass(huge);
new SubClass(huge);