前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 通过Object的clone复制对象

java 通过Object的clone复制对象

作者头像
六月的雨在Tencent
发布2024-03-28 20:35:50
680
发布2024-03-28 20:35:50
举报
文章被收录于专栏:CSDNCSDN
java 通过Object的clone复制对象

需求背景

对象的克隆是指创建一个新的对象,且新的对象的状态与原始对象的状态相同。当对克隆的新对象进行修改时,不会影响原始对象的状态。 常规实现

运行结果

这个时候发现如果改了p2的地址属性,p1的地址属性也改变了 原因分析 出现这种情况的原因Person p2 = p1;这里将p1赋值给p2实际是将p1的引用给p2,在堆内存中p1和p2指向的是同一个对象,怎样才能实现最初的需求呢?

需求实现

因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,clone()是object类的protected 方法,所以都不能在类外进行访问。

要想对一个对象进行复制,就需要对clone方法覆盖。 同时只有类的对象自己可以克隆自己,所以对象类必须实现Cloneable接口才可以使用obj.clone()方法, 首先,如果这个对象的类不实现接口{@code Cloneable},然后{@code CloneNotSupportedException}被抛出,典型的方式:

代码实现

运行结果

此时的结果p2更改的地址属性并没有影响到p1的地址属性,需求达到。 到此为止实现的对象clone方法属于浅复制(shallow copy),那么什么是深复制(deep copy) 深复制 大家都知道,在java语言中,分为基本数据类型和引用数据类型,基本数据类型包括(byte、short、int、long、float、double、boolean、char),引用数据类型包括(class、interface、[ ]),浅复制和深复制的主要区别就在于是否支持引用类型的成员变量的复制。 浅复制,clone()内部类似于创建一个新的对象并把对象中相应的字段通过赋值给新的对象,而引用数据类型的内容本身并不是克隆的,因此这种复制就叫浅复制。 那么 代码重现 增加Study对象

改造Person对象

运行程序

运行结果

可以看到p2更改的基础属性地址信息不影响p1的,但是p2更改的Study对象属性却会影响p1中对应的Study属性,这就是浅复制存在的问题 问题处理 在这种情况下需要对Study对象也实现Cloneable接口,同时重写clone方法覆盖

同时Person对象中需要处理Study对象的复制

这就是深复制 再次运行copy3()查看运行结果

这里可以看到p2对study属性的更改不再影响p1中study的属性。目标达成。

测试代码

TestClone.java

代码语言:javascript
复制
package com.example.demo;

import com.example.modules.person.domain.Person;
import com.example.modules.person.domain.Study;

/**
 * @author: dongao
 * @create: 2020/6/6
 */
public class TestClone {
    //测试clone
    public static void main(String[] args) {
        //copy();
        //copy2();
        copy3();
    }

    private static void copy() {
        Person p1 = new Person();
        p1.setName("小A");
        p1.setAddr("北京");
        p1.setAge(18);
        p1.setBirthday("2020-05-20");
        p1.setCountry("中国");
        System.out.println("p1-first:"+p1.getAddr());

        Person p2 = p1;
        System.out.println("p2-first:"+p2.getAddr());

        p2.setAddr("上海");
        System.out.println("p1-second:"+p1.getAddr());
        System.out.println("p2-second:"+p2.getAddr());
    }

    private static void copy2() {
        Person p1 = new Person();
        p1.setName("小A");
        p1.setAddr("北京");
        p1.setAge(18);
        p1.setBirthday("2020-05-20");
        p1.setCountry("中国");
        System.out.println("p1-first:"+p1.getAddr());

        Person p2 = p1.clone();
        System.out.println("p2-first:"+p2.getAddr());

        p2.setAddr("上海");
        System.out.println("p1-second:"+p1.getAddr());
        System.out.println("p2-second:"+p2.getAddr());
    }
    private static void copy3() {
        Person p1 = new Person();
        p1.setName("小A");
        p1.setAddr("北京");
        p1.setAge(18);
        p1.setBirthday("2020-05-20");
        p1.setCountry("中国");
        Study s1 = new Study();
        s1.setStuName("语文");
        p1.setStudy(s1);
        System.out.println("p1-first:"+p1.getAddr()+"study:"+p1.getStudy().getStuName());

        Person p2 = p1.clone();
        System.out.println("p2-first:"+p2.getAddr()+"study:"+p2.getStudy().getStuName());

        p2.setAddr("上海");
        p2.getStudy().setStuName("数学");
        System.out.println("p1-second:"+p1.getAddr()+"study:"+p1.getStudy().getStuName());
        System.out.println("p2-second:"+p2.getAddr()+"study:"+p2.getStudy().getStuName());
    }
}

Person.java

代码语言:javascript
复制
package com.example.modules.person.domain;

public class Person implements Cloneable
{
	private String id;
	private String name;
	private Integer age;
	private String country;
	private String birthday;
	private String addr;
	private String data;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	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;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getBirthday() {
		return birthday;
	}

	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}

	private Study study;

	public Study getStudy() {
		return study;
	}

	public void setStudy(Study study) {
		this.study = study;
	}
	@Override
	public Person clone() {
		Person per = null;
		try {
			per = (Person) super.clone();
			per.study = study.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return per;
	}

}

Study.java

代码语言:javascript
复制
package com.example.modules.person.domain;

/**
 * @author: dongao
 * @create: 2020/6/6
 */
public class Study implements Cloneable{
    private String stuName;

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    @Override
    public Study clone(){
        Study study = null;
        try {
             study = (Study) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return study;
    }
}

流方式复制对象

到这里基本问题都解决了,但是还可能会遇到一个问题,就是当前对象中有很多引用对象,这样的话通过clone的方法处理起来会比较麻烦,这是可以采用另外一种方式,序列化的方式来实现对象的深复制。 改造Person.java

这里最好显式指定serialVersionUID的值防止反序列化的时候出问题。

代码语言:javascript
复制
	public Person pclone() {

		Person per = null;
		try {
			//对象的序列化流,作用:把对象转成字节数据的输出到文件中保存,对象的输出过程称为序列化,可实现对象的持久存储。
			ByteArrayOutputStream bout = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bout);
			out.writeObject(this);
			out.close();

			// read a clone of the object from the byte array
			ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
			ObjectInputStream in = new ObjectInputStream(bin);
			per = (Person) in.readObject();
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return per;

	}

运行效果

**注:**大家可以自行复制代码测试,欢迎指正,相互学习。

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • java 通过Object的clone复制对象
  • 需求背景
  • 需求实现
  • 测试代码
  • 流方式复制对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com