1.原型模式
使用原型实例复制来创建新的对象。
2.利用Cloneable接口
浅复制
//需要实现Cloneable接口,否则不能克隆 public class PersonTest implements Cloneable { private ArrayList<String> hobby; public ArrayList<String> getHobby() { return hobby; } public void setHobby(ArrayList<String> hobby) { this.hobby = hobby; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
public class CloneObjectMethodTest {
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList<String> hobby = new ArrayList<>();
hobby.add("lili");
PersonTest person = new PersonTest();
person.setHobby(hobby);
/*浅复制,说明:例如String,Integer等不会出现问题的原因是使用了常量池技术,
* 他们直接指向的是常量池的结果而不是引用,当是其他的对象(未使用常量池的对象)时,
* 那么就指向的是引用,解决的方法将使用的引用对象依次复制
*/
PersonTest clone = (PersonTest)person.clone();
hobby.set(0, "sansan");
System.out.println(person.getHobby().get(0));//sansan
System.out.println(clone.getHobby().get(0));//sansan
}
}
深复制
//需要实现Cloneable接口,否则不能克隆
public class PersonTest implements Cloneable {
private static final String Person = null;
private ArrayList<String> hobby;
public ArrayList<String> getHobby() {
return hobby;
}
public void setHobby(ArrayList<String> hobby) {
this.hobby = hobby;
}
@Override
protected Object clone() throws CloneNotSupportedException {
PersonTest clone = (PersonTest) super.clone();
clone.hobby = (ArrayList<String>) this.hobby.clone();// 深度克隆,将指向的索引都复制一遍
return clone;
}
}
public class CloneObjectMethodTest { public static void main(String[] args) throws CloneNotSupportedException { ArrayList<String> hobby = new ArrayList<>(); hobby.add("lili"); PersonTest person = new PersonTest(); person.setHobby(hobby); PersonTest clone = (PersonTest)person.clone(); hobby.set(0, "sansan"); System.out.println(person.getHobby().get(0));//sansan System.out.println(clone.getHobby().get(0));//lili } }
3.利用序列化和反序列化实现深复制
//需要实现Serializable接口,否则不能序列化和反序列化 public class PersonTest implements Serializable { private static final String Person = null; private ArrayList<String> hobby; public ArrayList<String> getHobby() { return hobby; } public void setHobby(ArrayList<String> hobby) { this.hobby = hobby; } }
public class CloneObjectMethodTest { //序列化和反序列化实现的是深复制,原因是因为都是从文本中读取的,且反序列化是必须有相应的类已经编译, //然后在反序列化的过程中产生了新的对象和赋值动作 @SuppressWarnings("resource") public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException, IOException { ArrayList<String> hobby = new ArrayList<>(); hobby.add("lili"); PersonTest person = new PersonTest(); person.setHobby(hobby); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"))) { oos.writeObject(person); } catch (Exception e) { e.printStackTrace(); } try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"))) { hobby.set(0, "sansan"); PersonTest rdperson = (PersonTest) ois.readObject(); System.out.println(person.getHobby().get(0));//sansan System.out.println(rdperson.getHobby().get(0));//lili } catch (Exception e) { e.printStackTrace(); } } }
4.原型模式效率比较
结论:深复制,cloneable最快,Serializable较慢,new最慢
//New public void test(TestClone testClone) { long start = Instant.now().toEpochMilli(); for (int i = 0; i < 9; i++) { try { PersonTest1 personTest = new PersonTest1(); } catch (InterruptedException e) { e.printStackTrace(); } } long end = Instant.now().toEpochMilli(); System.out.println("testNew" + ":" + (end - start)); }
//testClone public void test(TestClone testClone) { long start = Instant.now().toEpochMilli(); try { if (!(testClone instanceof PersonTest2)) { return ; } PersonTest2 personTest = (PersonTest2) testClone; ArrayList<String> hobby = new ArrayList<>(); personTest.setHobby(hobby);// 1002 for (int i = 0; i < 9; i++) { Object clone = personTest.clone(); } } catch (Exception e) { e.printStackTrace(); } long end = Instant.now().toEpochMilli(); System.out.println("testClone" + ":" + (end - start)); }
//testSerializable public void test(TestClone testClone) { long start = Instant.now().toEpochMilli(); try { if (!(testClone instanceof PersonTest3)) { return; } PersonTest3 personTest = (PersonTest3) testClone; for (int i = 0; i < 9; i++) { PersonTest3 clonePersonTest = PersonTest3.clonePersonTest(personTest);// 1013 } } catch (Exception e) { e.printStackTrace(); } long end = Instant.now().toEpochMilli(); System.out.println("testSerializable" + ":" + (end - start)); } public static PersonTest3 clonePersonTest(PersonTest3 person) { try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"))) { oos.writeObject(person); } catch (Exception e) { e.printStackTrace(); } try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"))) { PersonTest3 rdperson = (PersonTest3) ois.readObject(); return rdperson; } catch (Exception e) { e.printStackTrace(); } return null; }
public class CompareTest implements Runnable { private TestClone testClone; public CompareTest(TestClone testClone) { super(); this.testClone = testClone; } @Override public void run() { try { testClone.test(testClone); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { ExecutorService fixPool = null; try { fixPool = Executors.newFixedThreadPool(3); fixPool.submit(new CompareTest((TestClone) new PersonTest1()));// testNew:9004 fixPool.submit(new CompareTest((TestClone) new PersonTest2()));// testClone:0 fixPool.submit(new CompareTest((TestClone) new PersonTest3()));// testSerializable:12 } catch (Exception e) { e.printStackTrace(); } finally { if (fixPool != null) { fixPool.shutdown(); } } } }