Java對象深復制與淺復制實例詳解
我們在遇到一些業務場景的時候經常需要對對象進行復制,對於對象的復制一般有兩種方式,深復制和淺復制
淺復制:對象的復制僅是對象本身,對象引用的其它對方並不會復制。
深復制:對象的復制包含對象引用的對象。
Java所有對象的基類提供了clone方法,但是這個方法是protected native修飾,因此只暴露給之類去重寫,外部是無法直接調用的。
我們現在來測試兩種復制,首選是淺復制,淺復制要實現Cloneable接口。
// 課程對象 class Class { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } // 學生對象 class User implements Cloneable { private String name; private Long id; // 課程引用 private Class c; public Class getC() { return c; } public void setC(Class c) { this.c = c; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public int hashCode() { return super.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof User) { User user = (User) obj; if (this.id == user.getId() && this.getName() == user.getName()) { return true; } if (user.getId().equals(this.id) && user.getName().equals(this.name)) { return true; } return false; } else return false; } }
我們來測試:
User user1 = new User(); User user2 = user1; User user3 = (User) user1.clone(); System.out.println(user1 == user2); System.out.println(user3 == user1); System.out.println(user3.equals(user1)); System.out.println(user3.getName() == user3.getName());// true,淺復制 Class c = new Class(); c.setName("語文"); user1.setC(c); // 測試復制深度 User user4 = (User) user1.clone(); System.out.println(user4.getC() == user1.getC()); // true,說明引用的對象依然是同一個對象
對象的復制並沒復制引用所指向的對象class,復制出來的引用指向的同一個地址。
深復制采用序列化與反序列的方式去獲取,也有種說法類似於腌菜,用流的方式腌制進去又取出來,實現深度復制。
class Car implements Serializable { /** * */ private static final long serialVersionUID = 42342L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } // 深復制 class People implements Serializable{ /** * */ private static final long serialVersionUID = 543535212412L; private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public People deepClone() throws IOException, ClassNotFoundException { // 腌制 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(this); // 取出 ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(input); return (People) ois.readObject(); } }
測試深復制:
// 深復制 Car car = new Car(); car.setName("benz"); People p = new People(); p.setCar(car); try { People p2 = p.deepClone(); System.out.println(p2.getCar() == p.getCar()); // false,說明引用的對象也進行了復制 } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); }
例外提及一下生成對象的五種辦法:
1.new
2.Class類的newInstance
3.Constructor類newInstance
4.Clone方式
5.反序列化的方式
其中2與3即是反射的方式。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!