我有一个类,其中超类在构造函数中读取一个巨大的对象(大量解析)来初始化它的值。在子类中,我需要来自该巨大对象的第二个值。我不想两次解析文件,并且我不想在内存中保留解析结果,因为它不再需要。
我想做的事情看起来像这样(在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;
}
也许使用回调?
答案 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);