1. 程式人生 > 其它 >List集合中物件拷貝遇到的坑

List集合中物件拷貝遇到的坑

技術標籤:java知識點

List集合中物件拷貝遇到的坑

簡單介紹

我們在平時開發過程中或多或少會遍歷一個java集合(暫且以List為例說明),然後根據遍歷的每一個物件,處理不同的業務邏輯,本文要闡述的是我們平時處理業務邏輯時會獲取資料庫的資料結果物件或者使用者編輯資料物件或者快取中的資料物件等等凡是不等於集合中遍歷結果的物件都可以,我們根據這些業務衍生的物件給集合遍歷結果的物件賦值,往往會發現明明同一個型別(同一個類)只是不同的例項而已,賦值給集合中的物件後 再去查詢集合的資料結果,發現集合中的物件還是以前的資料,是不是很奇怪,要知道具體什麼原因請耐心看我的後續解釋。

問題現象

為了直觀一些,我們先來看下這段程式碼和執行的效果

 List<LeanBO> leanBOList = new ArrayList<LeanBO>();
        LeanBO leanBO = new LeanBO();
        leanBO.setSno(202101L);
        leanBO.setSname("你好202101");
        leanBOList.add(leanBO);
        System.out.println("原始集合資料"+JSON.toJSONString
(leanBOList)); for (LeanBO leanTemp:leanBOList) { //模擬從資料庫查詢出息的leanBO物件 LeanBO leanBODB = new LeanBO(); leanBODB.setSno(202102L); leanBODB.setSname("你好202102"); leanTemp = leanBODB; } System.out.println("處理業務結束後的集合資料"
+JSON.toJSONString(leanBOList));

執行的效果如下:
在這裡插入圖片描述
大家看到執行結果是不是覺得詫異 怎麼回事?我不是把leanBODB賦值給集合遍歷的結果物件leanTemp了嗎?為什麼集合的資料還是以前的?

解釋原因

從以上程式碼可以看到是物件間的直接賦值,在資料結構上 其實就是leanBODB物件的引用地址指向了leanTemp,即兩個物件公用一個記憶體地址,但是新修改的地址沒有重新加入到連結串列中,因為連結串列中儲存的還是老的物件的引用地址,所以最終輸出的結果是賦值之前的資料

解決方法

1、可以把老的物件從集合中移除,然後再把新的業務物件加入到集合中,具體實現程式碼如下:

 List<LeanBO> leanBOList = new ArrayList<LeanBO>();
        LeanBO leanBO = new LeanBO();
        leanBO.setSno(202101L);
        leanBO.setSname("你好202101");
        leanBOList.add(leanBO);
        System.out.println("原始集合資料"+JSON.toJSONString(leanBOList));

        for (LeanBO leanTemp:leanBOList) {
             //模擬從資料庫查詢出來的leanBO物件
            LeanBO leanBODB = new LeanBO();
            leanBODB.setSno(202102L);
            leanBODB.setSname("你好202102");
            leanBOList.remove(leanTemp);//移除老的物件
            leanBOList.add(leanBODB);//加入新的物件
        }
        System.out.println("處理業務結束後的集合資料"+JSON.toJSONString(leanBOList));

執行的結果如下:

原始集合資料[{"sname":"你好202101","sno":202101}]
處理業務結束後的集合資料[{"sname":"你好202102","sno":202102}]

2、可以不修改原始集合中物件的引用,而是重新修改物件的屬性值,具體程式碼如下:

List<LeanBO> leanBOList = new ArrayList<LeanBO>();
        LeanBO leanBO = new LeanBO();
        leanBO.setSno(202101L);
        leanBO.setSname("你好202101");
        leanBOList.add(leanBO);
        System.out.println("原始集合資料"+JSON.toJSONString(leanBOList));

        for (LeanBO leanTemp:leanBOList) {
             //模擬從資料庫查詢出來的leanBO物件
            LeanBO leanBODB = new LeanBO();
            leanBODB.setSno(202102L);
            leanBODB.setSname("你好202102");
            leanTemp.setSno(leanBODB.getSno());//重新賦值sno
            leanTemp.setSname(leanBODB.getSname());//重新賦值sname
        }
        System.out.println("處理業務結束後的集合資料"+JSON.toJSONString(leanBOList));

執行結果如下:

原始集合資料[{"sname":"你好202101","sno":202101}]
處理業務結束後的集合資料[{"sname":"你好202102","sno":202102}]

3、可以採用第三方元件API:BeanUtils.copyproperties()深度拷貝物件