无限递归组合类



我的程序中有一个无限递归,其中一个类中的字段在其字段中具有相同的类。他们是单身汉,但这并不是导致他们不去构建的原因。顺便说一句,我写程序的时候,我实际上无法删除相位数组。

abstract class Phase{
  protected String phaseName;
  protected char[] keys;
  protected String[] commands;
  protected Phase[] phases;
  protected StringBuilder pattern;
}
class RemotePhase extends Phase{
  private static RemotePhase remotePhase;
  protected RemotePhase(){
    phaseName="Remote.";
    commands=new String[]{"Lock/unlock windows", "Toggle door", "Select dog menu"};
    setPattern();
    //Just below here starts an infinite loop
    phases=new Phase[]{FixWindows.getFixWindows(), ToggleDoor.getToggleDoor(), SelectDogPhase.getSelectDogPhase()};
  }
  public static RemotePhase getRemotePhase(){
    if(remotePhase==null){
      remotePhase=new RemotePhase();
    }
    return remotePhase;
  }
}
final class FixWindows extends Phase{
  private static FixWindows windows;
  private RemotePhase remotePhase;
  private FixWindows(){
    //execution keeps coming here as FixWindows object is never constructed
    remotePhase=RemotePhase.getRemotePhase();
  }
  public static FixWindows getFixWindows(){
    if(windows==null){
      windows=new FixWindows();
    }
    return windows;
  }
}

我曾尝试将RemotePhase作为一个静态类,FixWindows将其用于其成员,但我在试图覆盖抽象类的非静态方法时遇到了错误,并试图在非静态上下文中从FixWindows调用它们。不过,我更喜欢不让它成为静态的,因为我必须创建一个额外的类来引用RemotePhase。

不过,有什么方法可以让它发挥作用。感谢

为什么您需要存储对singleton的引用,而您总是可以通过静态getter访问它?这将允许从FixWindows延迟访问RemotePhase,并修复循环依赖关系。因此,最干净的修复方法就是不在FixWindows的构造函数内部调用getter。

final class FixWindows extends Phase{
  private static FixWindows windows;
  private FixWindows(){
      // does nothing but preventing external classes to instantiate it
  }
  public static synchronized FixWindows getFixWindows(){
    if(windows==null){
      windows=new FixWindows();
    }
    return windows;
  }
  public void methodThatRequiresTheRemotePhase(){
    doSomeStuff(RemotePhase.getRemotePhase());
  }
}

顺便说一句,我应该警告您,您的代码不是线程安全的。你的getter应该同步。

这是如何打破初始化循环的答案。但是@Dici的回答更好,因为您不应该首先存储对RemotePhase的单例引用

您的问题是单例初始化程序是相互依赖的。

打破这一点的一种方法是在初始化中的RemotePhase完成之前分配RemotePhase的静态单例字段。这将确保在初始化过程中,并且构造FixWindows单例对象时,它可以找到(部分(初始化的RemotePhase单例对象。

所以,机会代码是这样的:

private RemotePhase() {
    phaseName = "Remote.";
    commands = new String[] { "Lock/unlock windows",
                              "Toggle door",
                              "Select dog menu" };
    setPattern();
}
private void init() {
    phases = new Phase[] { FixWindows.getFixWindows(),
                           ToggleDoor.getToggleDoor(),
                           SelectDogPhase.getSelectDogPhase() };
}
public static RemotePhase getRemotePhase() {
    if (remotePhase == null) {
        remotePhase = new RemotePhase(); // assigns partially initialized object
        remotePhase.init();              // completes initialization
    }
    return remotePhase;
}

您应该避免在其他构造函数中调用构造函数。您可以使用setter。

我为FixWindows展示了这个想法,您可以将其用于其他子类

abstract class Phase{
  protected String phaseName;
  protected char[] keys;
  protected String[] commands;
  protected Phase[] phases;
  protected StringBuilder pattern;
}
class RemotePhase extends Phase{
  private static RemotePhase remotePhase;
  protected RemotePhase(){
    phaseName="Remote.";
    commands=new String[]{"Lock/unlock windows", "Toggle door", "Select dog menu"};
    setPattern();
    //Just below here starts an infinite loop
    phases=new Phase[]{FixWindows.getFixWindows(this), ToggleDoor.getToggleDoor(), SelectDogPhase.getSelectDogPhase()};
  }
  public static RemotePhase getRemotePhase(){
    if(remotePhase==null){
      remotePhase=new RemotePhase();
    }
    return remotePhase;
  }
}
final class FixWindows extends Phase{
  private static FixWindows windows;
  private RemotePhase remotePhase;
  private FixWindows(){
    //execution keeps coming here as FixWindows object is never constructed
    //remotePhase=RemotePhase.getRemotePhase(); //shoud be deleted
  }
  public static FixWindows getFixWindows(remotePhase){
    if(windows==null){
      windows=new FixWindows();
      windows.setRemotePahse(remotePhase);
    }
    return windows;
  }
}

最新更新