我有一个使用生成器(J Bloch样式)的图形(g)。需要反转图形以运行某些统计信息,然后将其缓存以供报告和分析算法访问。

因此,图g定义了以下参考变量:

private final Builder savedBuilder; // save builder for clone build with same properties.
private final Graph   gPrime;       // must reverse populated graphs BEFORE cache of stats


注意:gPrime指的是相同的图,只是它是由已替换的g填充的。
      gPrime.gPrime应该引用g,因为g与gPrime相反。

和构建器构建方法:

public Graph build() {
  Graph g = new Graph(this);
  g.gPrime.gPrime = g;
  return g;
}


以及采用构建器的构造器:

private Graph (Builder builder){  // 'this' used for clarity
  this.gType        = builder.gType;
  this.dropOrphans  = builder.dropOrphans;
  this.fileHandle   = builder.fileHandle;
  this.nodes        = builder.nodes;
  this.edges        = builder.edges;
  this.delimiter    = builder.delimiter;
  this.mapCapacity  = builder.mapCapacity;
  this.mapLoadFactor    = builder.mapLoadFactor;
  this.savedBuilder = builder;  // save builder for cloning

  emptyGraph();     // build empty structure for data in this graph
  if (this.fileHandle == null) {           // no file data
    if (this.nodes == 0) {         // no sizing info
    ;                  // nothing else to do - - - empty graph
    } else {                    // we have # of nodes
      if ( this.edges == 0) {            // just an edge-less integer graph)
      populateEdgeless(nodes)   ;
      } else {                 // randomly generated graph
    populateRandom(nodes, edges);
      }
    }
  } else {                 // populate from file
    populateFromFile();
  }

  // To create empty graph to transpose our values into,
  // we need to clear out builder settings that would populate a new graph.
  savedBuilder.fileHandle = null;
  savedBuilder.nodes = 0;
  savedBuilder.edges = 0;

  // otherwise, everything the same, so just pass modified builder to constructor
  // save the reference to this graph ( ready for the reversal method to use )
  this.gPrime = new Graph(savedBuilder);

)


再来一次。目标是两个图形对象,每个对象中的gPrime相互引用。

顺序为:
构建g---填充g---将g反转为具有与g相同特征的空图形

因此,这是我不太了解的问题。

如果将g分配给gPrime.gPrime,无论是在g构建之后的构建中还是在构造函数的底部,我都会收到一条错误消息,指出gPrime是最终的。 Eclipse表示这是有问题的第一个gPrime---是的---它是最终的并已分配。但是gPrime.gprime(着重于第二个gPrime)尚未分配。 (我搜索了整个程序。)

我还尝试将赋值放在反向方法的底部。一样。

我还在构建器中尝试了g.gPrime.gPrime。一样。

似乎编译器对于哪个gPrime正在接收分配感到困惑。

我确定有些事情我没有看到或理解---但是---不知道如何实现这一目标。

如果我拿下决赛,我可以做好这项工作,但我努力做到一成不变。

最佳答案

您需要不可变的循环依赖关系。您必须实现它,以便当您在A的构造器中使用Build A时,必须使用constructor调用Bthis

这是Builders的代码(您必须确保整个构建过程不会从当前线程中逸出):

public class A {

  private final B b_;
  private final String name_;

  private A(Builder b) {
    b_ = b.bB_.a(this).build();
    name_ = b.name_;
  }

  public String name() {
    return name_;
  }

  public B b() {
    return b_;
  }

  @Override
  public String toString() {
    return "[" + name_ + ": " + b_.name() + " ]";
  }

  public static class Builder {

    private B.Builder bB_;
    private String name_;

    public Builder bB(B.Builder bB) {
      bB_ = bB;
      return this;
    }

    public Builder name(String arg) {
      name_ = arg;
      return this;

    }

    public A build() {
      return new A(this);
    }
  }

}


B类:

public class B {

  private final A a_;
  private final String name_;

  private B(Builder b) {
    a_ = b.a_;
    name_ = b.name_;
  }

  public String name() {
    return name_;
  }

  @Override
  public String toString() {
    return "[" + name_ + ": " + a_.name() + " ]";
  }

  public static class Builder {

    private A a_;
    private String name_;

    public Builder a(A a) {
      a_ = a;
      return this;

    }

    public Builder name(String arg) {
      name_ = arg;
      return this;

    }

    public B build() {
      return new B(this);
    }
  }

}


如何使用它:

public class Main {

  public static void main(String[] args) {
    A.Builder aBl = new A.Builder().name("I am A1");
    B.Builder bBl = new B.Builder().name("I am B1");

    A a = aBl.bB(bBl).build();

    System.out.println(a);
    System.out.println(a.b());

  }

}


^
^
^
如果要具有单个类和两个循环依赖的对象):

public class A {

  private final A other_;
  private final String name_;

  private A(Builder b) {
    if (b.otherBulder_ != null) {
      other_ = b.otherBulder_.otherInstance(this).build();
    } else {
      other_ = b.otherInstance_;
    }
    name_ = b.name_;
  }

  @Override
  public String toString() {
    return "[" + name_ + ": " + other_.name() + " ]";
  }

  public String name() {
    return name_;
  }

  public A other() {
    return other_;
  }

  static class Builder {

    private Builder otherBulder_;
    private A otherInstance_;
    private String name_;

    Builder name(String name) {
      name_ = name;
      return this;
    }

    Builder otherBuilder(Builder other) {
      otherBulder_ = other;
      return this;
    }

    Builder otherInstance(A instance) {
      otherInstance_ = instance;
      return this;
    }

    A build() {
      return new A(this);
    }
  }

  public static void main(String[] args) {
    Builder a1B = new Builder().name("A1");
    Builder a2B = new Builder().name("A2");

    A a = a1B.otherBuilder(a2B).build();
    System.out.println(a);
    System.out.println(a.other());

  }
}

10-08 16:13