一文带你读懂java中的对象拷贝
更新时间:2023-10-06一、Java中的对象拷贝简介
在Java编程中,由于对象的存在,对象的拷贝是不可避免的一个操作。对象拷贝有两种方式,浅拷贝和深拷贝。浅拷贝是指拷贝对象的引用,而不是拷贝对象的内容。而深拷贝则是创建一个新的对象,同时将原对象的所有内容都拷贝到新对象中。在Java中,如果不使用拷贝的方法,而是直接将一个对象引用赋值给另一个对象引用,则这两个对象指向同一块存储空间。
class Person { private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class ObjectCopyDemo { public static void main(String[] args) { Person p1 = new Person(20, "John"); Person p2 = p1; System.out.println(p1 == p2); // true } }
二、Java中的浅拷贝
在Java中,浅拷贝是通过Object类中的clone()方法来实现的。该方法会创建一个新的对象,但是这个新对象只是将原对象的引用复制给了新对象,而没有拷贝原对象的内容。如果原对象中有引用类型的成员变量,那么拷贝后的对象和原对象会共用这些成员变量。因此,对于修改拷贝后的对象中的引用类型成员变量,原对象中的这些成员变量也会发生改变。
class Student implements Cloneable { private int age; private String name; private Subject subject; public Student(int age, String name, Subject subject) { this.age = age; this.name = name; this.subject = subject; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Subject getSubject() { return subject; } public void setSubject(Subject subject) { this.subject = subject; } @Override public Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } } class Subject { private String name; public Subject(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class ShallowCopyDemo { public static void main(String[] args) throws CloneNotSupportedException { Subject subject = new Subject("Math"); Student s1 = new Student(20, "John", subject); Student s2 = s1.clone(); System.out.println(s1 == s2); // false System.out.println(s1.getSubject() == s2.getSubject()); // true,s1和s2共用同一个Subject对象 } }
三、Java中的深拷贝
在Java中实现对象的深拷贝有多种方法,比如使用序列化和反序列化、使用copy constructor和使用Java深拷贝库等。这里我们介绍一种使用序列化和反序列化的方式实现深拷贝。
class Address implements Serializable { private int number; private String street; public Address(int number, String street) { this.number = number; this.street = street; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } } class Student implements Serializable { private int age; private String name; private Address address; public Student(int age, String name, Address address) { this.age = age; this.name = name; this.address = address; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Student 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 (Student) ois.readObject(); } } public class DeepCopyDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { Address address = new Address(100, "Main St"); Student s1 = new Student(20, "John", address); Student s2 = s1.deepCopy(); System.out.println(s1 == s2); // false System.out.println(s1.getAddress() == s2.getAddress()); // false,s1和s2拥有各自的Address对象 } }
四、总结
Java中的对象拷贝是Java编程中经常会遇到的一个操作,我们需要了解浅拷贝和深拷贝的区别,并掌握如何在代码中实现深拷贝。深拷贝可以使用多种方式实现,选择不同的方式取决于具体的场景和需求。