传统的拷贝方式:
// 创建一只叫sheep,1岁了的羊 Sheep sheep1 = new Sheep('sheep', 1); // 拷贝这只羊 Sheep sheep2 = new Sheep(sheep1.getName(), sheep1.getAge()); Sheep sheep3 = new Sheep(sheep1.getName(), sheep1.getAge()); Sheep sheep4 = new Sheep(sheep1.getName(), sheep1.getAge());
优点: 好理解,易操作
缺点: 在创建对象时需要频繁获取原对象的属性,效率低,代码冗长。
public class Sheep implements Cloneable { private String name; private String color; private int age; private String address = "蒙古羊"; //是对象,克隆会如何处理,默认是浅拷贝 public Sheep friend; public Sheep(String name, String color, int age) { this.name = name; this.color = color; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Sheep getFriend() { return friend; } public void setFriend(Sheep friend) { this.friend = friend; } //克隆该实例,使用默认的clone方法来完成,用默认的时候是前拷贝 @Override protected Object clone() { Sheep sheep = null; try { sheep = (Sheep) super.clone(); }catch (Exception e){ e.printStackTrace(); } return sheep; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", color='" + color + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }
用法:
public static main(String[] args) { Sheep sheep1 = new Sheep('sheep', 1); Sheep sheep2 = (Sheep)sheep1.clone(); }
现在进行演示:
定义一个 程序员 类
public class Developer implements Serializable, Cloneable { // 姓名;基本类型 + String 浅拷贝就可以搞定 public String name; // 他的电脑;这里需要深拷贝才能搞定 public Computer computer; public Developer() {} //深拷贝-方式1 使用clone方法 @Override protected Object clone() throws CloneNotSupportedException { Object obj = null; //这里完成对基本数据类型(属性)和String类型的克隆 obj = super.clone(); //对应用类型的属性,进行单独处理 Developer developer = (Developer) obj; developer.computer = (Computer) computer.clone(); return developer; } // 深拷贝-方式2 通过对象的序列化实现(推荐) // 推荐原因,模版代码,不用修改,而上面的方式,每加减一个属性都有可能需要修改clone方法 public Object deepClone(){ //创建流对象 ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { // 序列化 bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); // 当前这个对象以对象流的方式输出 oos.writeObject(this); // 反序列化 bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); // 这里会分配新的内存空间来保存新对象,整个流数据拷贝过去 Developer copyObj = (Developer) ois.readObject(); return copyObj; }catch (Exception e){ e.printStackTrace(); return null; }finally { try { bos.close(); oos.close(); bis.close(); ois.close(); }catch (Exception e){ System.out.println(e.getMessage()); } } } }
public class Computer implements Cloneable , Serializable { private String computerName; public Computer(String name) { computerName = name; } //因为该类的属性都是string类型,因此我们这里使用默认的clone完成即可 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
public class Clinet { public static void main(String[] args) throws CloneNotSupportedException { Developer p = new Developer(); p.name = "乔布斯"; p.computer = new Computer("Macbook"); Developer p2 = (Developer) p.deepClone(); p.name = "库克"; System.out.println("p.name=" + p.name + " p.computer=" + p.computer.hashCode()); System.out.println("p2.name=" + p2.name + " p2.computer=" + p2.computer.hashCode()); } }