但還要implements Cloneable,不然會報CloneNotSupportedException
2.可以將clone()的protected 改成 public,也可將回傳的 Object 改成指定的物件
3.原形模式
※無集合
public class ClassPrototype implements Cloneable { private String xxx; private Integer ooo; // setter/getter... public ClassPrototype() { System.out.print("default constructor!"); } @Override protected ClassPrototype clone() throws CloneNotSupportedException { return (ClassPrototype) super.clone(); } }
※
※
ClassPrototype prototype = new ClassPrototype(); prototype.setXxx("banana"); prototype.setOoo(20); ClassPrototype copyPrototype; try { copyPrototype = prototype.clone(); System.out.println(copyPrototype.getXxx()); System.out.println(copyPrototype.getOoo()); copyPrototype.setXxx("apple"); System.out.println(prototype.getXxx()); } catch (CloneNotSupportedException e) { e.printStackTrace(); }
※結果:
default constructor!banana
20
banana
※第一行會呼叫建構子,但複製的時候不會
※基本型態和 String,用 == 是false,沒有什麼問題
※淺複製、深複製
假設複製的物件是傳集合,複製好的物件會影響到原本的物件,就是淺複製;不會影響的就是深複製
※深複製
public class ClassPrototype implements Cloneable { private String xxx; private List<String> list; // setter/getter... public ClassPrototype() { System.out.print("default constructor!"); } @Override protected ClassPrototype clone() throws CloneNotSupportedException { return (ClassPrototype) super.clone(); } public static void main(String[] args) { ClassPrototype prototype = new ClassPrototype(); prototype.setXxx("banana"); prototype.setList(Arrays.asList("a", "b")); ClassPrototype copyPrototype; try { copyPrototype = prototype.clone(); System.out.println(copyPrototype.getXxx()); System.out.println(copyPrototype.getList()); copyPrototype.setList(Arrays.asList("c", "d")); System.out.println(copyPrototype.getList()); System.out.println(prototype.getList()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
※
※淺複製
public class ClassPrototype implements Cloneable { private ArrayList<String> list; // setter/getter... public ClassPrototype() { System.out.println("default constructor!"); } @SuppressWarnings("unchecked") @Override protected ClassPrototype clone() throws CloneNotSupportedException { ClassPrototype cp = (ClassPrototype) super.clone(); // cp.list = (ArrayList<String>) list.clone(); return cp; } public static void main(String[] args) { ClassPrototype prototype = new ClassPrototype(); ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b"); prototype.setList(list); ClassPrototype copyPrototype; try { copyPrototype = prototype.clone(); System.out.println(copyPrototype.getList()); copyPrototype.getList().add("c"); System.out.println(copyPrototype.getList()); System.out.println(prototype.getList()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
※想改成深複製,將註解打開即可,但因為 List 沒有實作 Cloneable,所以沒有 clone 方法可用,所以改了 ArrayList;也可用 cp.list.list = (ArrayList<String>) ((ArrayList<String>) list).clone();
※註解還沒打開時,使用 == 判斷會發現是 true
※注意:用 add 是正常的,但如果用 copyPrototype.setList(xxx),或將 copyPrototype new 一個全新的 copyPrototype,用 == 都會是 false,類似 call by reference 的問題
但將 copyPrototype = null ,然後在去.方法居然沒報錯,很奇怪
※自定物件
自定的和上面的集合都一樣,如下public class ClassPrototype implements Cloneable { private Book book; // setter/getter... @Override protected ClassPrototype clone() throws CloneNotSupportedException { ClassPrototype cp = (ClassPrototype) super.clone(); cp.book = book.clone(); return cp; } public static void main(String[] args) { ClassPrototype prototype = new ClassPrototype(); Book book = new Book(); book.setName("abc"); prototype.setBook(book); ClassPrototype copyPrototype; try { copyPrototype = prototype.clone(); System.out.println(copyPrototype.getBook().getName()); // 1.setter方式是OK的 // Book b = new Book(); // b.setName("def"); // copyPrototype.setBook(b); // 2.getter再 setter 也沒問題 copyPrototype.getBook().setName("def"); System.out.println(copyPrototype.getBook().getName()); System.out.println(prototype.getBook().getName()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } } class Book implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Book clone() throws CloneNotSupportedException { return (Book) super.clone(); } }
沒有留言:
張貼留言