原型模式
用于克隆对象。
利用场景:
- 因为拷贝要比从新创立一个对象快得多,所以当创立一个对象所耗资源很多时,能够思考应用拷贝。
- 避免原对象被批改,例如在并发环境下的一个ArrayList,若须要批改其中的值又怕会引起并发批改异样,能够思考克隆后操作,即保护性拷贝。
浅拷贝
实现Cloneable接口,重写clone()办法。
public class Sheep implements Cloneable{ private String id; private String name; private int age; private Sheep friend; public Sheep() { } public Sheep(String id, String name, int age, Sheep friend) { this.id = id; this.name = name; this.age = age; this.friend = friend; } public String getId() { return id; } public void setId(String id) { this.id = id; } 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 Sheep getFriend() { return friend; } public void setFriend(Sheep friend) { this.friend = friend; } @Override public String toString() { return "Sheep{" + "id='" + id + ''' + ", name='" + name + ''' + ", age=" + age + ", friend=" + friend + '}'; } @Override public Sheep clone() throws CloneNotSupportedException { return (Sheep) super.clone(); } }
测试
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Sheep sheep = new Sheep(); sheep.setAge(1); sheep.setName("teddy"); sheep.setFriend(new Sheep("1","tom",1,null)); Sheep cloneSheep=sheep.clone(); System.out.println(sheep); System.out.println(cloneSheep); System.out.println(sheep.hashCode()); System.out.println(cloneSheep.hashCode()); System.out.println(sheep.getFriend().hashCode());//援用是同一个 System.out.println(cloneSheep.getFriend().hashCode()); } }
输入
Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} 1956725890 356573597 1735600054 1735600054
阐明浅拷贝无奈克隆援用。
深拷贝
一、应用clone()
同样实现Cloneable()接口,
将clone办法批改为
@Override public Sheep clone(){ Sheep sheep=null; try { sheep=(Sheep) super.clone(); Sheep friendSheep = sheep.getFriend(); if (friendSheep!=null){ sheep.setFriend(friendSheep.clone()); } } catch (CloneNotSupportedException e) { e.printStackTrace(); } return sheep; }
留神:援用类型克隆前要判空。
测试输入:
Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} 607635164 529116035 242481580 1627800613
二、序列化
public Sheep deepClone(){ ByteArrayOutputStream out; ByteArrayInputStream in = null; ObjectInputStream oin = null; ObjectOutputStream oout=null; out = new ByteArrayOutputStream(); try { oout=new ObjectOutputStream(out); oout.writeObject(this); //要保障out中有内容写入,不然会报EOFException in = new ByteArrayInputStream(out.toByteArray()); oin=new ObjectInputStream(in); return (Sheep) oin.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }finally { try { if (oin!=null) { oin.close(); } if (oout!=null){ oout.close(); } out.close(); if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } } return null; }
流程:
- 实例化ByteArrayOutputStream;
- 实例化ObjectOutputStream;
- 写入对象
- 实例化ByteArrayInputStream
- 实例化ObjectInputStream
- 读出对象
留神:写入对象肯定要在实例化输出流之前,因为实例化ByteArrayInputStream传入输入流,以输入流中的内容读出对象,若输入流中没有内容,会在实例化ByteArrayInputStream时抛出EOFException。