2013-04-16 50 views
0

當我從我當前的foo(...)方法調用我的bar(Map map)方法時,遇到以下行爲,其中bar()表示map爲空。Java方法通過值問題

private void foo() { 
    Map map = new Map(); // pseudocode 
    // add (key, value)'s to map 
    printMap(map); // prints key and values 
    Map newMap = bar(map); 
    ... 
    System.out.println(newMap.size()); // returns 0 
} // end foo(); 

private Map bar(Map map) { 
    printMap(map); // return empty 
    ... 
} 

編輯:難道是這種印刷方法的調用it.remove()?當我刪除這個電話時,我不再有問題。

private void printMap(Map mp) { 
    Iterator it = mp.entrySet().iterator(); 
    while (it.hasNext()) { 
     Map.Entry pairs = (Map.Entry)it.next(); 
     logger.info(pairs.getKey() + " = " + pairs.getValue()); 
     it.remove(); // avoids a ConcurrentModificationException 
    } 
} 
+2

如果'printMap'是冪等的,你不應該觀察到的行爲=>顯示您的實際代碼。 – assylias

+1

在'bar'方法中發佈更多代碼..您在該方法中做了些什麼以及您從該方法返回的內容? –

+1

我沒有看到任何條目被添加到地圖,所以爲什麼它不應該是空的?試着用現有的代碼添加條目應該顯示出來。 – h22

回答

3

你明確地刪除項目:

it.remove(); 

然後,你將有一個空列表。因爲你通過引用將map傳遞給方法。

要處理異常,請使用try/catch塊或throw例外。

爲避免併發修改,您應該使用同步機制。

+0

他似乎只使用一個線程。他可以使用ConcurrentHashMap來允許併發訪問,但我相信混淆是相信Map已經被傳遞的值。 –

+0

確實,我認爲你的猜測是正確的。 – deepmax

2

一個常見的困惑是將Map看作一個對象,就像它在C++中一樣。不是這樣。它是對一個對象的引用。這意味着當您通過值傳遞參考時,僅複製參考。如果您將此引用更改爲另一個地圖,則這不會影響調用者。但是,如果您訪問引用並更改對象的內容,則調用者可以看到此更改。

在你的情況下,你正在移除地圖的條目,所以當你返回調用者看到一個空的地圖。

BTW打印地圖,所有你需要做的就是

private void logMap(Map<?,?> map) { 
    for(Map.Entry<?,?> entry : map.entrySet()) 
     logger.info(entry); // logs; key = value 
} 
+0

謝謝@Peter的解釋。 –