2014-11-23 58 views
1

請考慮Lecturer.java中的以下代碼。 Lecture.java中的二傳具有完全相同的形式。還請注意,感興趣的屬性是private如何保持1對1關係一致

public void setLecture(Lecture lecture) { 
    if (this.lecture == lecture) return; 

    if (this.lecture != null) { 
     this.lecture.setLecturer(null); 
    } 

    this.lecture = lecture; 

    if (this.lecture != null) { 
     this.lecture.setLecturer(this); 
    } 
} 

這種嘗試設置null值以前沒有null時導致一個無限循環。

我不敢相信這很難保持1:1的關係一致 - 但我無法弄清楚如何去做。如何解決這個問題?

+0

@Ogen該屬性應該是私人的。 – 2014-11-23 20:11:08

+0

既然有一個二傳手我想也有一個吸氣,對吧? – 2014-11-23 20:45:21

+0

@giannischristofakis Yessir。 – 2014-11-23 20:45:53

回答

0

最後,這裏是你的解決方案:

public class A { 
    private B b; 

    public void setB(B b) { 
     if(this.b != null) { 
      this.b.unsetA(); 
     } 
     this.b = b; 
     if(b != null && b.getA() != this) { 
      this.b.setA(this); 
     } 
    } 

    public void unsetB() { 
     this.b = null; 
    } 

    public B getB() { 
     return b; 
    } 

} 

public class B { 
    private A a; 

    public void setA(A a) { 
     if(this.a != null) { 
      this.a.unsetB(); 
     } 
     this.a = a; 
     if(a != null && a.getB() != this) { 
      this.a.setB(this); 
     } 
    } 

    public void unsetA() { 
     this.a = null; 
    } 

    public A getA() { 
     return a; 
    } 

} 

我的測試類:

public class Test { 

    public static void main(String ... args) { 
     A a1 = new A(); 
     B b1 = new B(); 
     A a2 = new A(); 
     B b2 = new B(); 

     checkForZeroOrTwoRelations(a1, a2, b1, b2); 
     a1.setB(b1); 
     checkForZeroOrTwoRelations(a1, a2, b1, b2);  
     b1.setA(a2); 
     checkForZeroOrTwoRelations(a1, a2, b1, b2); 
     b2.setA(a2); 
     checkForZeroOrTwoRelations(a1, a2, b1, b2); 
     b2.setA(null); 
     checkForZeroOrTwoRelations(a1, a2, b1, b2); 
    } 

    private static void checkForZeroOrTwoRelations(A a1, A a2, B b1, B b2) { 
     int i = 0; 
     if(a1.getB() != null) i++; 
     if(a2.getB() != null) i++; 
     if(b1.getA() != null) i++; 
     if(b2.getA() != null) i++; 
     if(i != 0 && i != 2) { 
      throw new IllegalStateException(); 
     } 
    } 
} 
+0

這也導致無限循環。 – 2014-11-23 20:14:04

+0

我已經添加了一個醜陋的解決方法。 – 2014-11-23 20:16:11

+0

來吧,你真的不想讓這種公開的方法,是嗎? – 2014-11-23 20:17:16

0

你只需要的對象屬性,以打破無限循環設置爲。但首先你必須將以前的值存儲到一個臨時變量中。它將在第一個if聲明處停止,其中null等於null

public void setLecture(Lecture lecture) { 

    if (this.lecture == lecture) { 
     return; 
    } 

    if (this.lecture != null) { 

     Lecture pastLecture = this.lecture; 
     this.lecture = null; 

     pastLecture.setLecturer(null); 

     pastLecture = null; 

    } 

    this.lecture = lecture; 

    if (lecture != null) { 
     lecture.setLecturer(this); 
    } 
} 

Gist

0

我張貼它作爲一個不同的答案的原因其實我覺得,我的第一個答案是,你在找什麼。

至於我的建議,你可以創建一個雙向映射(或者你可以使用Guava HashBiMap)來確保關係的完整性。

Map<Lecturer, Lecture> lecturerMap = new HashMap(); 
Map<Lecture, Lecturer> lectureMap = new HashMap(); 

public void addRelation(Lecturer lecturer, Lecture lecture) { 

    this.checkIntegrity(lecturerMap,lectureMap, lecturer, lecture); 
    this.checkIntegrity(lectureMap, lecturerMap, lecture, lecturer); 

    lecturerMap.put(lecturer, lecture); 
    lectureMap.put(lecture, lecturer); 
} 

private <T,V> void checkIntegrity(Map<T,V> mapf, Map<V,T> maps, T t, V v) { 
    if (mapf.containsKey(t)) { 
     V value = mapf.get(t); 

     if (maps.containsKey(value)) { 
      maps.remove(value); 
     } 

     mapf.remove(t); 
    } 
} 

確實有更復雜的方法可以做,但是這項工作也是如此。

Gist