clone為Object類的一個本地方法
protected native Object clone() throws CloneNotSupportedException;
要想對象具有拷貝功能則需要該類實作Cloneable接口,表示該類允許拷貝,并且在類中自定義clone調用Object類提供的繼承權限clone方法。
關于對象的兩種拷貝方式
1.淺拷貝
class Teacher implements Cloneable {
private String name;
private Integer age;
public Teacher(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable {
private String name;
private Integer age;
private Teacher teacher;
public Student(String name, Integer age, Teacher teacher) {
this.name = name;
this.age = age;
this.teacher = teacher;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestClone {
public static void main(String[] args) throws Exception {
Teacher teacher = new Teacher("lxy", 17);
Student student = new Student02("abc", 12, teacher);
Student clone = (Student)student.clone();
System.out.println(student == clone);//false
System.out.println(student.getTeacher()==clone.getTeacher());//true
}
}
由上面結果可以看出,淺拷貝出來的對象保留着原對象的中其他類的引用,在拷貝出來的對象中沒用建立其他類新的對象。
2.深拷貝
深拷貝:對拷貝出來的對象對于其所有引用建立産生新的對象。
實作方式:
1,包含的其他類實作cloneable接口,并且其他類的拷貝是來自自身類的clone方法
2,使用序列化,本類和本類包含的其他類實作Serializable。
1.代碼實作
class Teacher implements Cloneable {
private String name;
private Integer age;
public Teacher(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable {
private String name;
private Integer age;
private Teacher teacher;
public Student(String name, Integer age, Teacher teacher) {
this.name = name;
this.age = age;
this.teacher = teacher;
}
@Override
protected Student clone() throws CloneNotSupportedException {
Student temp = (Student) super.clone();
temp.teacher = (Teacher) this.teacher.clone();
return temp;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
public class TestClone{
public static void main(String[] args) throws Exception {
Teacher teacher = new Teacher("lxy", 17);
Student student = new Student("abc", 12, teacher);
Student clone =student.clone();
System.out.println(student == clone);//false
System.out.println(student.getTeacher()==clone.getTeacher());//false
}
}
2.代碼實作
class Teacher implements Serializable {
private String name;
private Integer age;
public Teacher(String name, Integer age) {
this.name = name;
this.age = age;
}
}
class Student implements Serializable {
private String name;
private Integer age;
private Teacher teacher;
public Student(String name, Integer age, Teacher teacher) {
this.name = name;
this.age = age;
this.teacher = teacher;
}
public Student cloneObject() throws IOException, ClassNotFoundException {
ByteOutputStream bos = new ByteOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.getBytes());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Student) ois.readObject();
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
public class TestClone {
public static void main(String[] args) throws Exception {
Teacher teacher = new Teacher("lxy", 17);
Student student = new Student02("abc", 12, teacher);
Student clone =student.clone();
System.out.println(student == clone);//false
System.out.println(student.getTeacher()==clone.getTeacher());//false
}
}
由結果可知拷貝出來的對象中對于其他對象的引用為新值。對任意對象的修改都不會對其他對象産生影響。
clone的替換方案
使用clone方法拷貝一個對象,過程比較複雜又有風險,建議不要用clone,可以使用拷貝構造函數。
代碼如下
class Teacher {
public Teacher() {
}
public Teacher(Teacher teacher) {
}
}
class Person {
String name;
Teacher teacher;
public Person() {
}
public Person(String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;
}
public Person(Person person) {
name = new String(person.name);
teacher = new Teacher(person.teacher);
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person("lyx", new Teacher());
Person p1 = new Person(p);
System.out.println(p == p1);//false
System.out.println(p.name);//lyx
System.out.println(p1.name);//lyx
p.name = "abc";
System.out.println(p.name);//abc
System.out.println(p1.name);//lyx
System.out.println(p.teacher == p1.teacher);false
}
}