1. Cloneable的用途
Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
2. 克隆的分类
浅克隆(shallow clone),浅克隆是指拷贝对象时仅仅copy对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
-
深克隆(deep clone),不仅copy对象本身,而且copy对象包含的引用指向的所有对象。
举例:对象X中包含对Y的引用,Y中包含对Z的引用。浅拷贝X得到X1,X1中依然包含对Y的引用,Y中依然包含对Z的引用。深拷贝则是对浅拷贝的递归,深拷贝X得到X1,X1中包含对Y1(Y的copy)的引用,Y1中包含对Z1(Z的copy)的引用。
3. 克隆代码举例
要让对象可以被克隆,应具备以下2个条件:
让该类实现java.lang.Cloneable接口;
重写(Override)Object的clone()方法;
package com.lgl;
public class Info implements Cloneable {
private int id;
private String text;
public Info(int id, String text) {
this.id = id;
this.text = text;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj.getClass()!= getClass()) {
return false;
}
Info temp = (Info) obj;
if (id != temp.id) {
return false;
}
if (text == null) {
if (temp.text != null) {
return false;
}
} else if (!text.equals(temp.text)) {
return false;
}
return true;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Info info1 = new Info(1, "I am Colyn Lu.");
Info info2 = (Info) info1.clone();
System.out.println(info1.getClass() == info2.getClass());//true
System.out.println(info1 == info2);//false
System.out.println(info1.equals(info2));//true
}
}
4. 浅克隆
package com.lgl;
public class MyFile implements Cloneable {
private String path;
private Info info;
public MyFile(String path, Info info) {
this.path = path;
this.info = info;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj.getClass()!= getClass()) {
return false;
}
MyFile temp = (MyFile) obj;
if (path == null) {
if (temp.path != null) {
return false;
}
} else if (!path.equals(temp.path)) {
return false;
}
if (info == null) {
if (temp.info != null) {
return false;
}
} else if (!info.equals(temp.info)) {
return false;
}
return true;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Info info = new Info(2, "Hello world.");
MyFile file1 = new MyFile("c:", info);
MyFile file2 = (MyFile) file1.clone();
System.out.println(file1.getClass() == file2.getClass());//true
System.out.println(file1 == file2);//false
System.out.println(file1.equals(file2));//true
System.out.println(file1.info.getClass() == file2.info.getClass());//true
System.out.println(file1.info == file2.info);//true
System.out.println(file1.info.equals(file2.info));//true
}
}
5.深克隆
深克隆需要重写(Override)Object类的clone()方法,并且在方法内部调用持有对象的clone方法。
package com.lgl;
public class MyFile2 implements Cloneable {
private String path;
private Info info;
public MyFile2(String path, Info info) {
this.path = path;
this.info = info;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj.getClass()!= getClass()) {
return false;
}
MyFile2 temp = (MyFile2) obj;
if (path == null) {
if (temp.path != null) {
return false;
}
} else if (!path.equals(temp.path)) {
return false;
}
if (info == null) {
if (temp.info != null) {
return false;
}
} else if (!info.equals(temp.info)) {
return false;
}
return true;
}
@Override
protected Object clone() throws CloneNotSupportedException {
MyFile2 file = (MyFile2) super.clone();
file.info = (Info) file.info.clone();
return file;
}
public static void main(String[] args) throws CloneNotSupportedException {
Info info = new Info(2, "Hello world.");
MyFile2 file1 = new MyFile2("c:", info);
MyFile2 file2 = (MyFile2) file1.clone();
System.out.println(file1.getClass() == file2.getClass());//true
System.out.println(file1 == file2);//false
System.out.println(file1.equals(file2));//true
System.out.println(file1.info.getClass() == file2.info.getClass());//true
System.out.println(file1.info == file2.info);//false
System.out.println(file1.info.equals(file2.info));//true
}
}