首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java List 存放物件重複問題:同一引用導致資料覆蓋

     編輯:程式設計疑難解答

問題現象

在 Servlet 中查詢資料庫,將每筆記錄封裝為 Menu 物件加入 List<Menu>,再存入 Session。但取出時發現 List 長度正確,所有元素卻都是最後一筆資料(如「秘制雞排 20.0」重複 6 次)。後台列印也同樣全為最後一筆。

錯誤代碼片段

private Menu menu = new Menu(); // 類成員變量,只 new 一次
// ...
while (rs.next()) {
    menu.setName(rs.getString("m_name"));
    menu.setPrice(Float.parseFloat(rs.getString("m_price")));
    menu.setPic(rs.getString("m_pic"));
    list.add(menu); // 每次 add 的是同一個 menu 實例
}

根本原因

menu 宣告為類成員變數,整個迴圈只有一個 Menu 實例。每次迴圈只是修改該實例的屬性值,然後將同一個引用重複加入 List。List 內部儲存的是引用地址,因此所有索引最終指向同一個物件,顯示的自然是最後一次賦值的結果。

正確做法

在迴圈內部每次 new 新物件:

while (rs.next()) {
    Menu menu = new Menu(); // 每筆資料對應一個獨立實例
    menu.setName(rs.getString("m_name"));
    menu.setPrice(Float.parseFloat(rs.getString("m_price")));
    menu.setPic(rs.getString("m_pic"));
    list.add(menu);
}

記憶體圖解

List 內部 elementData 陣列儲存的是引用地址

圖中 elementData 陣列每個槽位透過「=」指向同一個 Menu 物件地址,修改物件內容會影響所有槽位。

延伸提醒

  • 任何集合(List、Set、Map)存放物件時,若需保留歷史狀態,務必確保每次放入的是不同實例或深拷貝副本。
  • 同理,若在迴圈中建立 Map 放入 List,也要在迴圈內 new HashMap<>()。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved