Danny P. Danny P. - 3 months ago 25
Java Question

Infinite recursion composition class

I have an infinite recursion in my program where I have a field in a class, that has the same class in its field. They are singletons, but this is not what causes them not to construct. By the way I wrote the program I actually cannot remove the phases array.

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;
}
}


I have tried making RemotePhase a static class and FixWindows use it for its members, but I ran into errors trying to override the non static methods of the abstract class, and trying to call them from FixWindows in nonstatic context. I prefer to not make it static though, because I would have to make an additional class just to refer to RemotePhase.

Any ways to make this work though. Thanks

Answer

Why would you need to store a reference to a singleton while you can always access it by the static getter ? This would enable lazy access to RemotePhase from FixWindows, and fix your circular dependency. Therefore, the cleanest fix is simply to not call the getter inside the constuctor of FixWindows.

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());
  }
}

By the way, I should warn you that your code is not thread-safe. Your getters should be synchronized.

Comments