天天看點

如何在Java中複制對象(深、淺拷貝)?

如何在Java中複制對象?

考慮下面的代碼:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'      

是以,我想複制dum到dumtwo并且更改dum而不影響dumtwo。但是上面的代碼沒有做到這一點。當我更改時dum,也會發生相同的更改dumtwo。

我想,當我說時dumtwo = dum,Java僅複制參考。那麼,有什麼方法可以建立的新副本dum并将其配置設定給dumtwo?

高分回答:

建立一個副本構造函數:

class DummyBean {
  private String dummy;

  public DummyBean(DummyBean another){
    this.dummy = another.dummy; // you can access      

每個對象都有一個克隆方法,可用于複制對象,但不要使用它。建立類和執行不正确的克隆方法太容易了。如果您要這樣做,請至少閱讀Joshua Bloch在Effective Java中要說的話。

高分回答:

基本: Java中的對象複制。

讓我們假設一個對象- obj1,它包含兩個對象,containedObj1和containedObj2。

在此處輸入圖檔說明

如何在Java中複制對象(深、淺拷貝)?

淺表複制:

淺表複制建立instance相同類的新表,并将所有字段複制到新執行個體并傳回它。對象類提供了一種clone方法,并提供了對淺表複制的支援。

在此處輸入圖檔說明

如何在Java中複制對象(深、淺拷貝)?

深度複制:

深度複制是将對象及其引用的對象一起複制時發生的。下圖顯示了obj1在其上執行深度複制之後的情況。不僅已obj1被複制,而且包含在其中的對象也已被複制。我們可以Java Object Serialization用來制作深層副本。不幸的是,這種方法也存在一些問題(詳細示例)。

在此處輸入圖檔說明

如何在Java中複制對象(深、淺拷貝)?

可能的問題:

clone難以正确實施。

最好使用防禦性複制,複制構造函數(如@egaga回複)或靜态工廠方法。

如果您有一個對象,就知道它有一個公共clone()方法,但是在編譯時卻不知道該對象的類型,那麼您就遇到了問題。Java有一個名為的接口Cloneable。在實踐中,如果要建立對象,則應實作此接口Cloneable。Object.clone是protected,是以我們必須使用公共方法覆寫它,以便對其進行通路。

當我們嘗試對複雜對象進行深度複制時,會出現另一個問題。假設所有成員對象變量的方法也都進行深層複制,那麼進行假設的風險太大。您必須控制所有類中的代碼。clone()