本文內容來自於:深淺克隆面試題彙總——附詳細答案
1.使用克隆有什麼好處?
答:好處包含以下幾點:
- 使用方便:假如要複製一個對象,但這個對象中的部分屬性已經被修改過了,如果不使用克隆的話,需要給屬性手動賦值,相比克隆而已麻煩很多;
- 性能高:查看 clone 方法可以知道,它是 native 方法,native 方法是原生函數,使用操作系統底層的語言實現的,因此執行效率更高;
- 隔離性:克隆可以確保對象操作時相互隔離。
2.淺克隆和深克隆有什麼區別?
答:區別主要在對引用類型的複製上,具體信息如下:
- 淺克隆:只會複製對象的值類型,而不會複製對象的引用類型;
- 深克隆:複製整個對象,包含值類型和引用類型。
3.如何實現淺克隆?
答:克隆的對象實現 Cloneable 接口,並重寫 clone() 方法就可以實現淺克隆了。
4.以下代碼執行的結果是?
import java.util.Arrays;
class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
CloneObj cloneObj = new CloneObj();
cloneObj.name = "老王";
cloneObj.age = 30;
cloneObj.sistersAge = new int[]{18, 19};
CloneObj cloneObj2 = (CloneObj) cloneObj.clone();
cloneObj2.name = "磊哥";
cloneObj2.age = 33;
cloneObj2.sistersAge[0] = 20;
System.out.println(cloneObj.name + "|" + cloneObj2.name);
System.out.println(cloneObj.age + "|" + cloneObj2.age);
System.out.println(Arrays.toString(cloneObj.sistersAge) + "|" + Arrays.toString(cloneObj2.sistersAge));
}
}
class CloneObj implements Cloneable {
public String name;
public int age;
public int[] sistersAge;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
答:執行結果如下。
老王|磊哥
30|33
[20, 19]|[20, 19]
5.深克隆如何實現?有幾種實現方式?
答:一般實現方式有以下兩種:
- 通過序列化實現深克隆(序列化實現方式:Java 原生序列化、JSON 序列化、Hessian 序列化);
- 所有引用類型都實現克隆,從而實現深克隆。
6.爲什麼不能直接使用 Object 的 Clone 方法,還要重寫 clone() 方法之後才能實現克隆?
首先,看一下Cloneable接口的源碼:
public interface Cloneable {
}
我們奇怪的發現Cloneable竟然是空的,那麼我們爲什麼要實現Cloneable接口呢?
其實Cloneable接口僅僅是一個標誌,而且這個標誌也僅僅是針對 Object類中 clone()方法的,如果 clone 類沒有實現 Cloneable接口,並調用了 Object 的 clone() 方法(也就是調用了 super.Clone() 方法),那麼Object 的 clone() 方法就會拋出CloneNotSupportedException異常。
雖然所有類都是 Object 的子類,但因爲 Object 中的 clone() 方法被聲明爲 protected 訪問級別,所以非 java.lang 包下的其他類是不能直接使用的。因此要想實現克隆功能,就必須實現 Cloneable,並重寫 clone() 方法纔行。
7.序列化可不可以實現深克隆?實現的原理是什麼?
答:先將原對象序列化到內存的字節流中,再從字節流中反序列化出剛剛存儲的對象,這個新對象和原對象就不存在任何地址上的共享,這樣就實現了深克隆。