天天看點

java深入了解淺拷貝和深拷貝

雲栖号資訊:【 點選檢視更多行業資訊

在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

簡介

拷貝對象是java中經常會遇到的問題。java中存在兩種類型,基礎類型和引用類型。

java的指派都是傳值的,對于基礎類型來說,會拷貝具體的内容,但是對于引用對象來說,存儲的這個值隻是指向實際對象的位址,拷貝也隻會拷貝引用位址。

因為引用對象的存在,是以經常會出現和預期不一樣的情況。

本文将會深入的探讨一下在拷貝對象中會出現的淺拷貝和深拷貝的情況。

拷貝接口

java中所有的對象都是繼承自java.lang.Object。Object對象中提供了一個clone方法,來供我們對java對象進行拷貝。

java深入了解淺拷貝和深拷貝

這個clone方法是native的,是以不需要我們來實作,但是注意clone方法還是protected,這意味着clone方法隻能在java.lang包或者其子類可見。

如果我們想要在一個程式中調用某個對象的clone方法則是不可以的。因為clone方法是定義在Object中的,該對象并沒有對外可見的clone方法。

JDK的建議是讓我們去實作接口Cloneable,實作了這個接口就表示這個對象可以調用Object的clone方法。

注意,即使你實作了Cloneable接口,還是無法在外部程式中調用該對象的clone方法:

java深入了解淺拷貝和深拷貝

因為Cloneable是空的,明沒有強制要你去實作clone方法。

這是JDK在設計上的問題,導緻clone方法并不像預期那麼好用。

首先clone隻是對象的拷貝,它隻是簡單的拷貝對象,而不會去執行對象的構造函數。

其次clone會導緻淺拷貝的問題。

使用clone導緻的淺拷貝

我們舉個clone産生的淺拷貝的例子,我們定義一個對象中的對象,然後嘗試拷貝:

java深入了解淺拷貝和深拷貝
java深入了解淺拷貝和深拷貝

上面的例子中,我們定義了CustUser和Address。

java深入了解淺拷貝和深拷貝

淺拷貝我們隻調用了CustUser的clone方法。看下輸出結果:

java深入了解淺拷貝和深拷貝

我們可以看到拷貝之後的Address變化會影響到被拷貝的對象。

上面的例子我們還要關注兩個點:第一點String是不可變的。不管是拷貝還是指派,String都是不可變的。

第二點,上面的例子中我們定義了一個數組,可以看到如果隻是調用clone的話,數組也是淺拷貝。

使用clone的深拷貝

要使用深拷貝,隻需要修改CustUser的構造函數就可以了:

java深入了解淺拷貝和深拷貝

在重寫的clone方法中,我們分别調用了CustUser,Address和數組的clone方法來進行拷貝。

再運作一次上面的測試代碼:

java深入了解淺拷貝和深拷貝

可以看到address和cars是不同的,這表示我們的深拷貝是成功的。

不要overridden clone

上面的例子我們是通過overridden Object的clone方法來實作的。

但是最佳實踐是不要overridden clone。那我們怎麼做呢?

使用構造函數來建構新的對象:

java深入了解淺拷貝和深拷貝
java深入了解淺拷貝和深拷貝

據說數組直接用clone來拷貝會更快,也可以使用下面的方式來拷貝數組:

java深入了解淺拷貝和深拷貝

總結

本文講解了淺拷貝和深拷貝的應用,并對clone方法做了深入的探讨。

【雲栖号線上課堂】每天都有産品技術專家分享!

課程位址:

https://yqh.aliyun.com/live

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-05-11

本文作者:flydean

本文來自:“

掘金

”,了解相關資訊可以關注“掘金”