Java中的對象拷貝

我們在開發中有時候會經常需要進行對象拷貝的情況,舉個例子

  public static void main(String[] args) {
        m1(o);
        m2(o);
    }
    public static void m1(Object o){
		//會對o進行修改
    }
    public static void m2(Object o){
		//會對o進行修改
    }

此時我們在m1和m2中就需要對入參參數進行拷貝並使用,否則會污染原參數到底其他方法產生問題。

淺拷貝

Java提供了clone()來實現對象的拷貝,但其默認拷貝是淺拷貝。
什麼是淺拷貝?

public static void main(String[] args) throws Exception{
        TestClone testClone = new TestClone(1,"jwb", Collections.emptyList());
        TestClone clone = testClone.clone();

    }
    
class TestClone implements Cloneable{
    private int number;
    private String name;
    private List<String> list;
    
    @Override
    protected TestClone clone() throws CloneNotSupportedException {
        return (TestClone) super.clone();
    }
}

在這裏插入圖片描述
從斷點中我們可以看到,源對象和克隆對象中的引用類型屬性(String類型的name屬性,List類型的list屬性)的對象地址是相同的,即共享了同一個對象,這時候我們在源對象中或克隆對象中更改這些屬性,都會造成另一個對象中的該屬性發生改變,因爲它們本身就是共有的同一個屬性對象。

不止是默認的clone方法,我們平時經常使用的Spring提供的BeanUtils.copyProperties其實也是淺拷貝的

public static void main(String[] args) throws Exception{
        TestClone testClone = new TestClone(1,"jwb", Collections.emptyList());
//        TestClone clone = testClone.clone();
        TestClone clone = new TestClone();
        BeanUtils.copyProperties(testClone,clone);
    }

在這裏插入圖片描述

如何實現深拷貝?

  1. 重寫對象的clone方法,手動實現
  2. 對象序列化,再反序列化爲對象
  3. 各種工具類,其實現原理同樣是基於java序列化的,如commons.lang3

第一種方法這裏就不贅述了,我們這裏演示一下第二種和第三種

fastjson
public static void main(String[] args) throws Exception{
        TestClone testClone = new TestClone(1,"jwb", Collections.emptyList());
        TestClone clone = JSON.parseObject(JSON.toJSONString(testClone),TestClone.class);
        System.out.println(testClone);
}

在這裏插入圖片描述

commons.lang3

 public static void main(String[] args) throws Exception{
        TestClone testClone = new TestClone(1,"jwb", new ArrayList<>());
        TestClone clone = SerializationUtils.clone(testClone);
        System.out.println(testClone);
    }

在這裏插入圖片描述
注意其底層是基於Java序列化的,因此克隆類必須實現Serializable接口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章