Java调用构造函数多次

4
我有一个类,它基本上是这样的:
class Child extends Parent {
  public void reinitialize() {
    super();  // illegal
  }
}

基本上,我想再次调用构造函数以重新初始化。我无法将初始化代码重构为自己的方法,因为Parent是一个库类,我无法修改源代码。
有没有办法做到这一点?

你想要重新初始化父级还是子级? - PermGenError
创建一个 initialize() 方法,它执行您当前构造函数的操作。然后,您的构造函数和 reinitialize() 都应该简单地调用 initialize() - FThompson
@Gan:孩子(所以我可以改为调用this())。Vulcan:正如我所提到的,由于没有Parent的源代码,我无法进行重构。 - Xodarap
4个回答

7
没有办法实现这个。即使在JVM字节码级别,一条<init>方法(构造函数)链也只能在任何给定对象上调用一次。
通常的解决方法是将代码重构为普通实例方法,但正如您所说,这是不可能的。
最好的方法是找到一种方式来重新设计以避免重新初始化的需要。或者,如果父构造函数中有特定的行为需要,您可能可以自己复制它。

如果限制只在于不能调用<init>超过一次,那么使用Objenesis实例化Child(它将跳过第一次构造函数的调用)是否可以解决这个问题? - Pr0methean
我正在尝试将您所说的内容与能够使用this(.)在同一对象上调用多个不同构造函数进行协调。参见https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html。 是否可以帮忙解释一下为什么您的陈述没有包括这种情况? - flow2k
@flow2k 在任何给定的构造函数中,您只能调用一次构造函数。每个构造函数的字节码都是独立验证的。您在同一个运行时对象上调用多个方法的事实是无关紧要的。我可以详细解释,但无法在 Stack Overflow 评论的限制内完成。如果您仍然不理解,请随时提问。 - Antimony
@Antimony 由于某种原因,我最初将您的答案解读为“在任何给定对象上,构造函数最多只能被调用一次”;但现在仔细阅读后,我认为我应该将其解读为“在任何给定对象上,构造函数链最多只能被调用一次”,这样就有意义了。 - flow2k
抱歉,我想我能理解我的初始答案有些令人困惑。如果您调用一系列构造函数,则每个构造函数在进入时都会将对象视为未初始化,并在链接的构造函数返回后进行初始化。最终,实际执行初始化的是java/lang/Object的构造函数。 - Antimony
显示剩余4条评论

3

唯一的解决方法是:

  • 每次需要“重新初始化”时创建一个新对象。
  • 使用委托而不是继承,即使您必须同时使用两者。通过使用委托,您可以替换实例。
  • 创建一个重新初始化方法,该方法执行与父构造函数相同的操作。例如,替换字段或清除集合,必要时使用反射。

1
一种方法是提供一个静态方法,该方法返回一个新的Child对象。或者,您可以在客户端代码中直接创建一个新的Child对象。无论哪种方式,都似乎无法重用现有对象。

0

有几种方法可以实现这个目标。其中之一是创建另一个方法,例如“init”。这个“init”方法应该从构造函数或重新初始化方法中调用。


谢谢,但正如问题中所提到的,我无法修改父类的构造函数。 - Xodarap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接