一、什麼是深拷貝
在Java對象的拷貝過程中,有時候只是單純的複製了引用,指向同一個對象,在這種情況下,對拷貝後的對象進行修改,會直接影響原對象,這就是淺拷貝。而深拷貝則是在拷貝的過程中對所有的屬性和引用對象都進行重新創建,使得原對象和拷貝後的對象完全獨立。
下面是一個淺拷貝和深拷貝的示例代碼:
// 淺拷貝示例
class Person1 implements Cloneable {
public int age;
public List skills;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Person1 p1 = new Person1();
p1.age = 18;
p1.skills = new ArrayList(Arrays.asList("Java", "Python", "C"));
Person1 p2 = (Person1) p1.clone();
p2.skills.add("PHP");
System.out.println(p1.skills); // [Java, Python, C, PHP]
// 深拷貝示例
class Person2 implements Cloneable {
public int age;
public List skills;
@Override
public Object clone() throws CloneNotSupportedException {
Person2 person = (Person2) super.clone();
person.skills = new ArrayList(skills);
return person;
}
}
Person2 p1 = new Person2();
p1.age = 18;
p1.skills = new ArrayList(Arrays.asList("Java", "Python", "C"));
Person2 p2 = (Person2) p1.clone();
p2.skills.add("PHP");
System.out.println(p1.skills); // [Java, Python, C]
二、使用Java自帶的Cloneable接口進行深拷貝
Java提供了一個Cloneable接口,實現該接口的類可以使用clone方法進行對象的拷貝。在進行深拷貝時,需要在clone方法中對引用類型的屬性進行重新創建,避免共用同一個對象。
示例代碼:
class Person implements Cloneable {
public int age;
public List skills;
@Override
public Object clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.skills = new ArrayList(skills);
return person;
}
}
Person p1 = new Person();
p1.age = 18;
p1.skills = new ArrayList(Arrays.asList("Java", "Python", "C"));
Person p2 = (Person) p1.clone();
p2.skills.add("PHP");
System.out.println(p1.skills); // [Java, Python, C]
三、使用序列化實現深拷貝
另一種實現深拷貝的方法是使用Java的序列化機制。通過把對象序列化成二進制流,再將其反序列化生成新對象,可以得到完全獨立的對象。需要注意的是,被拷貝的類及其引用對象都需要實現序列化接口。
示例代碼:
class Person implements Serializable {
public int age;
public List skills;
public Person deepCopy() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (Person) ois.readObject();
}
}
Person p1 = new Person();
p1.age = 18;
p1.skills = new ArrayList(Arrays.asList("Java", "Python", "C"));
Person p2 = p1.deepCopy();
p2.skills.add("PHP");
System.out.println(p1.skills); // [Java, Python, C]
四、使用第三方庫實現深拷貝
除了Java自帶的Cloneable接口和序列化機制外,還可以借用第三方庫來實現深拷貝。例如Apache Commons庫提供的SerializationUtils.copy方法,該方法可以將一個對象序列化,再反序列化生成新的對象。
示例代碼:
class Person {
public int age;
public List skills;
}
Person p1 = new Person();
p1.age = 18;
p1.skills = new ArrayList(Arrays.asList("Java", "Python", "C"));
Person p2 = SerializationUtils.clone(p1);
p2.skills.add("PHP");
System.out.println(p1.skills); // [Java, Python, C]
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/297795.html
微信掃一掃
支付寶掃一掃