Java对象克隆

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接口,将对象序列化到一个流里面,再反序列化出来。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值