- Java程序員面試筆試寶典(第2版)
- 何昊等編著
- 1441字
- 2022-06-17 16:00:40
1.3 Java中clone方法的作用
由于指針的存在不僅會給開發(fā)人員帶來不便,同時也是造成程序不穩(wěn)定的根源之一,為了消除C/C++語言的這些缺點,Java語言取消了指針的概念,但這只是在Java語言中沒有明確提供指針的概念與用法,而實質上每個new語句返回的都是一個指針的引用,只不過在大部分情況下開發(fā)人員不需要關心如何去操作這個指針而已。
由于Java取消了指針的概念,所以開發(fā)人員在編程中往往忽略了對象和引用的區(qū)別。如下例所示:


上述代碼的輸出結果為:

上面兩個看似類似的方法卻有著不同的運行結果,主要原因是Java在處理基本數據類型(例如int、char、double等)的時候,都是采用按值傳遞(傳遞的是輸入參數的拷貝)的方式,除此之外的其他類型都是按引用傳遞(傳遞的是對象的一個引用)的方式執(zhí)行。對象除了在函數調用的時候是引用傳遞,在使用“=”賦值的時候也采用引用傳遞,示例代碼如下:

上述代碼的運行結果為:

在實際的編程中,經常會遇到從某個已有的對象A創(chuàng)建出另外一個與A具有相同狀態(tài)的對象B,并且對B的修改不會影響到A的狀態(tài),例如Prototype(原型)模式中,就需要復制(clone)一個對象實例。在Java語言中,僅通過簡單的賦值操作顯然無法達到這個目的,而Java提供了一個簡單且有效的clone方法來滿足這個需求。
Java中所有的類默認都繼承自Object類,而Object類中提供了一個clone方法。這個方法的作用是返回一個Object對象的拷貝,這個拷貝函數返回的是一個新的對象而不是一個引用。那么怎樣使用這個方法呢?以下是使用clone方法的步驟:
1)實現clone的類首先需要繼承Cloneable接口。Cloneable接口實質上是一個標識接口,沒有任何接口方法。
2)在類中重寫Object類中的clone方法。
3)在clone方法中調用super.clone()。無論clone類的繼承結構是什么,super.clone()都會直接或間接調用java.lang.Object類的clone()方法。
4)把淺拷貝的引用指向原型對象新的克隆體。
對上面的例子引入clone方法如下:

程序運行結果為:

在C++語言中,當開發(fā)人員自定義拷貝構造函數的時候,會存在淺拷貝與深拷貝之分。Java在重載clone方法的時候也存在同樣的問題,當類中只有一些基本的數據類型的時候,采用上述方法就可以了,但是當類中包含了一些對象的時候,就需要用到深拷貝了,實現方法是對對象調用clone方法完成深拷貝后,接著對對象中的非基本類型的屬性也調用clone方法完成深拷貝。如下例所示:

運行結果為:

那么在編程的時候如何選擇使用哪種拷貝方式呢?首先,檢查類有無非基本類型(即對象)的數據成員。如果沒有,則返回super.clone()即可,如果有,則要確保類中包含的所有非基本類型的成員變量都實現了深拷貝。

引申:
(1)淺拷貝和深拷貝的區(qū)別
淺拷貝(Shallow Clone):被復制對象的所有變量都含有與原來對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之,淺拷貝僅僅復制所考慮的對象,而不復制它所引用的對象。
深拷貝(Deep Clone):被復制對象的所有變量都含有與原來對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量將指向被復制的新對象,而不再是原有的那些被引用的對象。換言之,深拷貝把復制的對象所引用的對象都復制了一遍。
假如定義如下一個類:

圖1-1給出了對這個類的對象進行拷貝時,淺拷貝與深拷貝的區(qū)別。

圖1-1 深拷貝與淺拷貝的區(qū)別
從圖1-1可以看出,對于淺拷貝而言,新的對象中的變量i有單獨的存儲空間,但是對于s而言,只拷貝了它的引用,從而導致新對象與原來的對象中的s指向相同的字符串。而深拷貝則為s指向的字符串單獨分配了一塊存儲空間。
(2)clone()方法的保護機制
clone()方法的保護機制在Object中是被聲明為protected的。以User類為例,通過聲明為protected,就可以保證只有User類里面才能“克隆”User對象,原理可以參考前面關于public、protected、private的講解。
- The Complete Rust Programming Reference Guide
- Google Apps Script for Beginners
- TypeScript Blueprints
- 編寫整潔的Python代碼(第2版)
- Groovy for Domain:specific Languages(Second Edition)
- Oracle Exadata專家手冊
- UVM實戰(zhàn)
- Java程序設計案例教程
- 深入淺出Go語言編程
- Learning Material Design
- Python:Deeper Insights into Machine Learning
- SpringBoot從零開始學(視頻教學版)
- MySQL 8從零開始學(視頻教學版)
- Java高并發(fā)編程詳解:深入理解并發(fā)核心庫
- 深入實踐C++模板編程