關於Java中的Map的淺拷貝和深拷貝問題
阿新 • • 發佈:2021-02-01
技術標籤:使用筆記
關於Java中的Map的淺拷貝和深拷貝問題
發生背景
- 生產列印的log會有圖片的Base64碼 這並不是我們實際日誌中需要關心的東西
- 想定的解決案是在切面列印日誌類中刪除掉列印log的欄位
使用過程
-
根據方法的引數做區分 定位到對應的引數是 刪除掉引數中的圖片欄位
- 程式碼
if (args.length == 1 && args[0] instanceof Map){ Map<String,Object> argMap = (Map)args[0]; argMap.remove("picture"); log.
產生問題
- 進入真正呼叫的方法的時候,出現引數校驗問題,返回異常資訊請求的必要引數為空
問題分析
-
真正獲取的是map的深拷貝資訊(物件地址)
-
刪除map中的物件,會把引數中的物件一起刪除掉
問題引申
- Java中的淺拷貝和深拷貝問題
- 什麼時候應該使用淺拷貝
- 什麼時候應該使用深拷貝
- 使用淺拷貝就一定沒有對應問題了嗎
深入研究
-
淺拷貝:只複製物件的引用,兩個引用指向同一個物件,在記憶體中佔用同一塊記憶體,被複制物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用仍然指向原來的物件,換言之,淺拷貝僅僅複製所考慮的物件,而不復制它所引用的物件。
-
深拷貝:被複制物件的所有變數都含有與原來的物件相同的值,除去那些引用其他物件的變數,那些引用其他物件的變數將指向被複制過的新物件,而不再是原有的那些被引用的物件,換言之,深拷貝把要複製的物件所引用的物件都複製了一遍。
-
程式碼
-
淺拷貝
public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("name", "jack"); Map<String, String> copyMap = new HashMap<>(); // 淺拷貝 使用=賦值 copyMap = map; map.remove("name"); System.out.println("map : " + map); System.out.println("copyMap : " + copyMap); } ======> 執行結果 map : {} copyMap : {}
-
深拷貝
public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("name", "jack"); Map<String, String> copyMap = new HashMap<>(); // 深拷貝 使用putAll // 或者使用構造器 一樣可以實現深拷貝 // Map<String, String> copyMap = new HashMap<>(map); copyMap.putAll(map); map.remove("name"); System.out.println("map : " + map); System.out.println("copyMap : " + copyMap); } ======> 執行結果 map : {} copyMap : {name=jack}
-
-
總結
- 實現淺拷貝的方式有1種:=
- 實現深拷貝有兩種:Map.putAll()和構造器
- 使用=進行賦值的方法,並不是真正意義上的拷貝,Map物件B只是對Map物件A進行了引用,當Map物件A中的內容發生變化時,Map物件B也會發生變化;
- 使用Map呼叫putAll()方法才是真正意義上的拷貝。