什麼要使用克隆、如何實現克隆物件、序列化與反序列實現克隆的好處、深拷貝與淺拷貝
1、為什麼要使用克隆
物件的拷貝需要使用克隆,如果想對一個物件進行處理,又想保留原有的資料進行接下來的操作,就需要使用克隆了,Java語言中克隆針對的是類的例項。
2、如何實現克隆物件
有兩種方式:
(1)實現Cloneable介面並重寫Object類中的clone()方法。
(2)實現Serializable介面,通過物件的序列化和反序列化實現克隆,可以實現真正的深度克隆。
程式碼舉例
public class MyUtil {
private MyUtil() {
throw new AssertionError();
}
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj)
throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin =
new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
// 說明:呼叫ByteArrayInputStream
//或ByteArrayOutputStream物件的close方法沒有任何意義
// 這兩個基於記憶體的流只要垃圾回收器清理物件就能夠釋放資源,
//這一點不同於對外部資源(如檔案流)的釋放
}
}
class Person implements Serializable {
private static final long serialVersionUID
= -9102017020286042305L;
private String name; // 姓名
private int age; // 年齡
private Car car; // 座駕
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person [name=" + name + ",
age=" + age + ", car=" + car + "]";
}
}
class Car implements Serializable {
private static final long serialVersionUID
= -5713945027627603702L;
private String brand; // 品牌
private int maxSpeed; // 最高時速
public Car(String brand, int maxSpeed) {
this.brand = brand;
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car [brand=" + brand + ",
maxSpeed=" + maxSpeed + "]";
}
}
class CloneTest {
public static void main(String[] args) {
try {
Person p1 = new Person("郭靖", 33, new Car("Benz", 300));
Person p2 = MyUtil.clone(p1); // 深度克隆
p2.getCar().setBrand("BYD");
// 修改克隆的Person物件p2關聯的汽車物件的品牌屬性
// 原來的Person物件p1關聯的汽車不會受到任何影響
// 因為在克隆Person物件時其關聯的汽車物件也被克隆了
System.out.println(p1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、序列化與反序列實現克隆的好處
基於序列化和反序列化實現的克隆不僅僅是深度克隆,更重要的是通過泛型限定,可以檢查出要克隆的物件是否支援序列化。
這項檢查是編譯器完成的,不是在執行時丟擲異常,這種方案明顯優於使用Object類的clone方法克隆物件。讓問題再編譯時候暴露,總是好過把問題留到執行時。
4、深拷貝與淺拷貝
深拷貝將物件及值複製過來,兩個物件修改其中任意的值,另一個值不會改變。
深克隆就是原型物件不管成員變數是什麼型別都要複製一份克隆物件,原型物件和克隆物件是兩個完全獨立的物件。
例如JSON.parse()和JSON.stringfy(),但是此方法無法複製函式型別。
淺拷貝只是複製了物件的引用地址,兩個物件指向同一個記憶體地址,所以修改其中任意值,另一個值都會隨之改變。
參考文章
https://blog.csdn.net/Certain_/article/details/108116710
https://blog.csdn.net/weixin_41847891/article/details/100213928
https://blog.csdn.net/ilovekdd/article/details/108812255
相關文章
- java深克隆(深拷貝)和淺克隆(淺拷貝)Java
- js 淺拷貝(淺複製、淺克隆)、深拷貝(深複製、深克隆)JS
- 三目運算、物件克隆、深拷貝和淺拷貝物件
- 淺拷貝與深拷貝的實現
- 實現物件淺拷貝、深拷貝物件
- 【JS】深拷貝與淺拷貝,實現深拷貝的幾種方法JS
- 【JavaScript】物件的淺拷貝與深拷貝JavaScript物件
- 深拷貝和淺拷貝的區別是什麼?實現一個深拷貝
- js物件實現深淺拷貝!!JS物件
- js實現深拷貝和淺拷貝JS
- 原生js實現物件的深克隆以及淺克隆JS物件
- 淺拷貝與深拷貝
- [JS系列二]談談深拷貝和淺拷貝,如何實現深拷貝JS
- 前端戰五渣學JavaScript——深克隆(深拷貝)前端JavaScript
- PHP 物件導向 - 物件的淺拷貝與深拷貝PHP物件
- Python淺拷貝與深拷貝Python
- JS深拷貝與淺拷貝JS
- python深拷貝與淺拷貝Python
- Javascript 中的克隆(拷貝)問題JavaScript
- 淺談深拷貝與淺拷貝?深拷貝幾種方法。
- 物件深拷貝和淺拷貝物件
- 深入淺出深拷貝與淺拷貝
- 深入淺出的“深拷貝與淺拷貝”
- 談談深拷貝與淺拷貝
- 賦值、淺拷貝與深拷貝賦值
- 深拷貝、淺拷貝與Cloneable介面
- React之淺拷貝與深拷貝React
- JavaScript中的淺拷貝與深拷貝JavaScript
- 聊聊物件深拷貝和淺拷貝物件
- 圖解 Python 淺拷貝與深拷貝圖解Python
- 淺拷貝與深拷貝程式碼(javascript)JavaScript
- ES6深拷貝與淺拷貝
- 安卓/Java物件拷貝(淺/深拷貝、兩種序列化、Beans等工具)安卓Java物件Bean
- 理解JS中的淺拷貝與深拷貝JS
- js中深克隆與淺克隆JS
- JS中的深淺拷貝以及實現深拷貝的幾種方法.JS
- 怎麼實現深拷貝
- 淺拷貝&深拷貝