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

发布于 2024-12-01 22:42:21 字数 357 浏览 2 评论 0原文

我有两个类,如下所示:

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

有什么方法可以从上述类中删除循环依赖..?

I have two classes which are as follows :

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

Is there any way i can remove circular dependency from the above classes..?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

↙厌世 2024-12-08 22:42:21

不,没有,但这没问题。

JAVA中循环依赖是没有问题的。如果您想在两个方向上遍历结构,那么拥有这些是很常见的。想象一棵树,其中父级和子级彼此了解,从而创建循环依赖关系。

垃圾收集器将检测循环依赖性并很好地处理这个问题。

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

No there isn't but that's no problem.

There is no problem with having circular dependency in JAVA. It's quite common to have those if you want to traverse structures in both directions. Think a tree where the parent and child knows of each other thus creating a circular dependency.

The Garbage Collector will detect circular dependencies and handle this just fine.

The only problems occur when having circular dependencies in both constructors which will result in an stack overflow :)

扛起拖把扫天下 2024-12-08 22:42:21

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

No, unless you remove one of the maps.

等往事风中吹 2024-12-08 22:42:21

根据您所拥有的知识,您不需要两门课程。尝试使该类更加通用,而您只需要一个。

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

Based on what you have, you don't need two classes. Try to make the class more generic and you only need one.

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.
}
葮薆情 2024-12-08 22:42:21

如果您有两个相互引用的类,那么如果您同时编译这两个类,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

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

If you have two classes which reference each other, javac will resolve that if you compile both at the same time:

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`

but if you enter:

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

it will resolve the circular compiler dependency.

挥剑断情 2024-12-08 22:42:21

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

:->你为什么要这样做?
因为 findbugs 在 Pattern: CD_CIRCULAR_DEPENDENCY 中这么说:
该类与其他类存在循环依赖关系。这使得构建这些类变得困难,因为每个类都依赖于另一个类才能正确构建。考虑使用接口来打破硬依赖。

另外 维基百科 说:
...在软件设计中,较大软件模块之间的循环依赖关系
由于它们的负面影响而被认为是反模式......
循环依赖通常是由没有经验的程序员引入的......

(this is actually a comment, but I don't have enough reputation points to do that)

:->why would you like to do that?
because findbugs says so in Pattern: CD_CIRCULAR_DEPENDENCY:
This class has a circular dependency with other classes. This makes building these classes difficult, as each is dependent on the other to build correctly. Consider using interfaces to break the hard dependency.

also wikipedia says:
...in software design circular dependencies between larger software modules
are considered an anti-pattern because of their negative effects...
Circular dependencies are often introduced by inexperienced programmers...

清音悠歌 2024-12-08 22:42:21
public class A{
private String id ;
private SortedMap<String,A> answer;
private String text;
}
public class B extends A{
} 

如果您觉得需要,或者只是在 A 中使用布尔字段

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

if you feel you need, or just use a boolean field in A

策马西风 2024-12-08 22:42:21

回顾上一个问题 - 您可以更改 xml 架构并向答案添加某种 标记。那么等效的 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>

您可能也想使用唯一的 id 作为答案,或者如果您想重用不同问题的答案(多对多),甚至可以再次反应模型 关系)

而你的类:

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

当然存在循环依赖,但这是绝对需要的,并且是从模型现实生活领域继承的。

Looking back to the previous question - you could change the xml schema and add some sort of <nextquestion> tag to answers. The equivalent xml document then would be:

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

You may want to use unique ids for the answers too or even reactor the model again if you want to reuse answers for different questions (many-to-many relationship)

And you classes:

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

And of course there is a circular dependency but that is absolutely wanted and inherited from the models real-life domain.

青衫负雪 2024-12-08 22:42:21

尝试类似的东西:

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

try something like:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文