2016-08-21 21 views
0

我正在用Java編寫一個程序,它有點像服務器。我得到了一個MemberController,MemberController它從數據庫或從緩存中獲取Members(加速過程)。這是它的外觀的例子:Java - 當我得到一個值並且改變時,集合總是改變

public class MemberController { 

    private final TMap<Integer, Member> members; 

    public MemberController() { 
     this.members = new THashMap<>(); 
    } 

    public Member getMemberByID(int id) { 
     if (members.containsKey(id)) { 
      return members.get(id); 
     } 

     // GET DATA FROM DB 
     members.put(ID, MEMBER); 
     return MEMBER; 
    } 

現在,Member包含BadgeController對象,其中包含了一個徽章TMap。的Member例如:

public class Member { 
    // FIELDS OF MEMBER HERE 
    private BadgeController badgeController; 

    public Member(ResultSet set) { 
     // SET FIELDS 
    } 

    public void InitOtherData() { 
     badgeController = new BadgeController(id); 
    } 

    public BadgeController getBadgeController() { 
     return badgeController; 
    } 

而且BadgeController

public class BadgeController { 

    private final int memberId; 
    private final TMap<String, Badge> badges; 

    public BadgeController(int memberId) { 
     this.memberId = memberId; 
     this.badges = new THashMap<>(); 

     // LOAD FROM DB 
    } 

    public Badge getBadge(String code) { 
     return badges.get(code); 
    } 

現在,我想知道的幾件事(所有,實際上是指我猜想的一樣):

  1. 如果我得到一個Membermembers,像members.get(1),我編輯對象,如下所示:

    Member member = members.get(1); member.setId(1);

請問這個編輯idTMap裏面嗎?所以如果我再次做members.get(1),它有更新的值?

  • 如果非要從上面的構件,並且我改變Badge的值,例如我做的:
  • Member member = members.get(1); member.getBadgeController().getBadge('500Members').setActive(true);

    請問這個結果在真正被打印?

    System.out.println(members.get(1).getBadgeController().getBadge('500Members').getActive()); 
    

    我希望我的解釋足夠好。我很難解釋它。對不起。

    +0

    你爲什麼不測試它?也就是說,你可能會預優化,並打開一大堆蠕蟲:你現在必須處理緩存中的過時數據,併發訪問非線程安全的可變數據結構等。只需使用數據庫,速度很快。 –

    +0

    我想知道它是否始終有效。解釋起來很複雜,測試也很複雜。它比這更深入。 –

    +1

    是的,它始終有效。沒有數據結構會永遠製作你的對象的副本。他們只是存儲引用。 –

    回答

    1

    Member member = members.get(1);不復制對象,但只是做一個快捷方式(參考)。更改member也會影響您的設置中的項目。

    要創建一個有效的副本,你必須讓你的對象從Cloneable接口繼承,並調用clone()方法獲取副本。

    +0

    無論我走多深都不重要?例如,我做了一個參考,然後我設置了'BadgeController',然後我改變了'badge'集合中的東西,這些更改都是在原始的'members'集合中完成的? –

    +0

    @ jean-françois-fabre我認爲最好使用複製構造函數:) – ceph3us

    +0

    是的,它是你正在處理的同一個對象。 –

    1

    需要DEEP拷貝對象是:

    • 實現克隆接口
    • 創建一個拷貝構造函數(如克隆簡單的解決方案)

    例子:

    // simple copy constructor 
        public SomerController(SomeController original) { 
         members = orginal.clone(); 
        } 
    
    
        // more advanced copy constructor 
        public SomeController(SomeController original) { 
         Set<Map.Entry<String, String>> entries = orginal.members.entrySet(); 
         members = new HashMap<String,Class>(); 
         Iterator<Map.Entry<String, Class>> iterator = entries.iterator(); 
         while(iterator.hasNext()) { 
          Map.Entry<String, String> next = iterator.next(); 
          String key = next.getKey(); 
          // if class contains a collections (maps, arrays) 
          // you need to provide a copy here 
          // ensure to copy whole tree of references 
          Class value next.getValue(); 
          map.put(key,value); 
         } 
        } 
    
    相關問題