1、为什么需要对象克隆?
在处理一些拥有很多属性的对象时,一个一个的get然后set属性会很麻烦,所以用到clone()方法,可以很方便的克隆一个一模一样的新对象出来。
2、如何实现克隆?
克隆又分为浅克隆与深克隆,具体解释让我们用代码说话。
public class Teacher implements Cloneable,Serializable{
private String name;
private Integer age;
public Teacher(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args){
Teacher teacher = new Teacher("哈哈",44);
}
}
package object2oriented.objectclone;
import java.io.*;
import java.util.function.Function;
/**
* @Author: dyf
* @Date: 2019/7/24 21:43
* @Description: 对象克隆
*/
public class Student implements Cloneable, Serializable{
private String name;
private Integer password;
private Teacher teacher;
public Student(String name, Integer password, Teacher teacher) {
this.name = name;
this.password = password;
this.teacher = teacher;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPassword() {
return password;
}
public void setPassword(Integer password) {
this.password = password;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
protected Object ShallowClone() throws CloneNotSupportedException {
return super.clone();//这样是浅克隆,只会克隆student一层,不会克隆他的引用对象teacher,只会复制地址值
}
protected Object deepClone() throws CloneNotSupportedException {
Student s = (Student) super.clone();
s.setTeacher((Teacher) s.getTeacher().clone());//这样才是深克隆,前提teacher也要实现cloneable接口,覆写clone方法
return s;
}
/*
大家知道,Java可以把对象序列化写进一个流里面,反之也可以把对象从序列化流里面读取出来,但这一进一出,这个对象就不再是原来的对象了,就达到了克隆的要求。
通过把对象写进ByteArrayOutputStream里,再把它读取出来。注意这个过程中所有涉及的对象都必须实现Serializable接口,由于涉及IO操作,这种方式的效率会比前面的低。
*/
public Student serializableClone() throws IOException, ClassNotFoundException {
Student clone;
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
clone = (Student) oi.readObject();
return clone;
}
@Override
public boolean equals(Object obj) {
Student s = (Student) obj;
if(s.getName().equals(name) && s.getPassword() == password && s.getTeacher().equals(teacher))return true;
return false;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", password=" + password +
", teacher=" + teacher +
'}';
}
static Function<Object, String> getAdress = s -> s.getClass().getName() + Integer.toHexString(s.hashCode());//获取对象的地址值
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Teacher teacher = new Teacher("张老师本尊", 40);
Student student = new Student("小明本尊", 16, teacher);
Student clone = (Student) student.ShallowClone();
// Student clone = (Student) student.deepClone();
// Student clone = (Student) student.serializableClone();
System.out.println(clone == student);
System.out.println(clone.equals(student));
System.out.println(getAdress.apply(student.getName()) + " | " + getAdress.apply(student.getPassword()) + " | " + getAdress.apply(student.getTeacher()));
System.out.println(getAdress.apply(clone.getName()) + " | " + getAdress.apply(clone.getPassword()) + " | " + getAdress.apply(clone.getTeacher()));
System.out.println(student);
System.out.println(clone);
System.out.println("克隆对象做出改变================================");
clone.setName("克隆学生");
clone.setPassword(123);
clone.getTeacher().setName("克隆张老师");
System.out.println("名字一样:" + (clone.getName() == student.getName()));
System.out.println("密码一样:" + (clone.getPassword() == student.getPassword()));
System.out.println("老师一样:" + (clone.getTeacher() == student.getTeacher()));//克隆出来的老师依然是一样的,这是浅克隆
System.out.println(getAdress.apply(student.getName()) + " | " + getAdress.apply(student.getPassword()) + " | " + getAdress.apply(student.getTeacher()));
System.out.println(getAdress.apply(clone.getName()) + " | " + getAdress.apply(clone.getPassword()) + " | " + getAdress.apply(clone.getTeacher()));
System.out.println(student);
System.out.println(clone);
}
}
总结:
1、浅克隆时,类必须实现Cloneable接口。只能克隆一层。
2、深克隆时,有两种方式来实现、
第一种是将需要二层甚至多层克隆的类也实现Cloneable接口,覆写clone方法。
第二种是让类实现Serializable接口,将对象序列化到一个流里面,再反序列化出来。