如何从两个具体类型的类中删除循环依赖

时间:2011-08-30 05:53:36

标签: java circular-dependency

我有两个课程如下:

public class A{
private String id ;
private SortedMap<String,B> answer = new TreeMap<String,B>();
private String text;
}

public class B{
private String id = null ;
private SortedMap<String,A> question = new TreeMap<String,A>();
private String text = null;
}

有没有办法可以从上面的类中删除循环依赖...?

8 个答案:

答案 0 :(得分:4)

没有,但没有问题。

在JAVA中具有循环依赖性没有问题。如果你想在两个方向上遍历结构,那么拥有它们是很常见的。想想父母和孩子彼此了解的树,从而创建循环依赖。

垃圾收集器将检测循环依赖关系并处理此问题。

在两个构造函数中都存在循环依赖关系时会出现唯一的问题,这会导致堆栈溢出:)

答案 1 :(得分:1)

不,除非您删除其中一张地图。

答案 2 :(得分:1)

根据您所拥有的内容,您不需要两个课程。尝试使这个类更通用,你只需要一个。

public class AB {
    private final String id ;
    private final SortedMap<String,AB> answer = new TreeMap<String,AB>();
    private final String text;
    private final boolean isA; // if you need to know if its an A or B.
}

答案 3 :(得分:1)

如果你有两个相互引用的类,如果同时编译两个类,javac将解决这个问题:

file: dev/A.java
class A {
    B b = null;
    public A(B b)
    {
        this.b = b;
    }
};

file: dev/B.java
package dev;
class B {
    A a = null;
    public B(A a )
    {
        this.a = a;
    }
};

$ javac -d classes dev/A.java
dev/A.java:3: cannot find symbol
symbol  : class B
location: class dev.A
    B b = null;
^
dev/A.java:4: cannot find symbol
symbol  : class B
location: class dev.A
    public A(B b)
             ^
2 errors
$ javac -d classes dev/B.java
dev/B.java:3: cannot find symbol
symbol  : class A
location: class dev.B
    A a = null;
    ^
dev/B.java:4: cannot find symbol
symbol  : class A
location: class dev.B
    public B(A a ) 
         ^
2 errors`

但是如果你输入:

$ javac -d classes dev/A.java dev/B.java

它将解决循环编译器依赖。

答案 4 :(得分:1)

(这实际上是一个评论,但我没有足够的声誉点来做到这一点)

: - &gt;你为什么要这样做?
因为findbugs在模式中这样说:CD_CIRCULAR_DEPENDENCY: 此类与其他类具有循环依赖关系。这使得构建这些类很困难,因为每个类都依赖于另一个来正确构建。考虑使用接口来打破硬依赖。

wikipedia说: ...在软件设计中较大的软件模块之间的循环依赖关系 被认为是一种反模式,因为它们的负面影响...... 循环依赖通常由经验不足的程序员引入......

答案 5 :(得分:0)

public class A{
private String id ;
private SortedMap<String,A> answer;
private String text;
}
public class B extends A{
} 

如果您觉得需要,或者只是在A

中使用布尔字段

答案 6 :(得分:0)

回顾上一个问题 - 您可以更改xml架构并为答案添加某种<nextquestion>标记。那么等效的xml文档将是:

<decision>
  <question id="0">
    <questionText>What type is your OS?</questionText>
    <answer id="0">
      <answerText>windows</answerText>
    </answer>
    <answer id="1">
      <answerText>linux</answerText>
    </answer>
    <answer id="2">
      <answerText>mac</answerText>
    </answer>
  </question>
  <question id="1">
    <questionText>What are you looking for?</questionText>
    <answer id="0">
      <answerText>table</answerText>
      <!-- NEW TAG HERE -->
      <nextquestion refid="3" />
    </answer>
    <answer id="1">
      <answerText>chair</answerText>
    </answer>
    <answer id="2">
      <answerText>bed</answerText>
    </answer>
    <answer id="3">
      <answerText>cloth</answerText>
    </answer>
  </question>
  <!-- ALL QUESTIONS ARE CHILDREN OF ROOT WITH UNIQUE ID -->
  <question id="3">
    <questionText>Which color table you want?</questionText>
    <answer id="0">
      <answerText>green</answerText>
    </answer>
    <answer id="1">
      <answerText>black</answerText>
    </answer>
    <answer id="2">
      <answerText>pink</answerText>
    </answer>
  </question>
</decision>

您可能也希望使用 unique ids 作为答案,如果您想重复使用不同问题的答案(多对多关系),甚至可以再次使用模型)

你上课:

public class Question {
  private int id;
  private String text;
  private Set<Answer> answers;
  // ...
}

public class Answer {
  private int id;
  private String text;
  private Question nextQuestion;
}

当然有一个循环依赖,但绝对需要从模型真实域中继承

答案 7 :(得分:0)

尝试类似:

import java.util.*;
class Question {
    Question(int id, String question) {
        this.id = id;
        this.question = question;
    }
    static void toString(Question question, StringBuffer sb, int indent) {
        for(int i=0;i<indent;i++)
            sb.append('\t');
        sb.append(question.id).append(' ').append(question.question).append('\n');
        for (Map.Entry<Integer, Answer> entry : question.answers.entrySet()) {
            Answer answer = entry.getValue();
            for(int i=0;i<=indent;i++)
                sb.append('\t');
            sb.append(entry.getKey()).append(' ').append(answer.answer).append('\n');
            if (answer.question != null)  {
                toString(answer.question, sb, indent+2);
            }
        }
    }
    public String toString() {
        StringBuffer sb = new StringBuffer();
        toString(this,sb, 0);
        return sb.toString();
    }
    int id;
    String question;
    SortedMap<Integer, Answer> answers = new TreeMap<Integer, Answer>();
}
class Answer {
    Answer(int id, String answer) {
        this.id = id;
        this.answer = answer;
    }
    final int id;
    final String answer;
    Question question; // may be null
}
public class Main {
    public static void main(String[] args) {
        Question q0 = new Question(0, "What are you looking for?");
        Answer a0 = new Answer(0, "table");
        q0.answers.put(a0.id, a0);
        a0.question = new Question(0, "Which color table you want?");
        a0.question.answers.put(0, new Answer(0, "green"));
        System.out.println(q0);
    }
}