但還要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();
}
}
沒有留言:
張貼留言