Java实现对象复制的方法实例

 更新时间:2023年08月02日 09:00:17   作者:ghostxiechuan  
这篇文章主要介绍了Java实现对象复制的方法实例,深复制:复制出来的对象中的变量(包括基本类型和字符串)和原来的对象的值都相同,引用对象也会指向复制出来的对象,需要的朋友可以参考下

一、概念

1.浅复制:复制出来的对象中的变量(包括基本类型和字符串)和原来的对象的值都相同,但是引用对象仍然指向原来的对象。

2.深复制:复制出来的对象中的变量(包括基本类型和字符串)和原来的对象的值都相同,引用对象也会指向复制出来的对象。

浅复制与深复制的不同之处就在于深复制还会复制对象的引用对象。

二、实现复制

1.使用Cloneable接口实现对象的复制

⑴浅复制

代码如下

public class Food {
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
public class Animal implements Cloneable {
	// 动物名
	private String name;
	// 食物
	private Food food;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Food getFood() {
		return food;
	}
	public void setFood(Food food) {
		this.food = food;
	}
	public Animal clone() {
		Animal animal = null;
		try {
			animal = (Animal) super.clone(); 
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return animal;
	}
}
public class TestCopy {
	public static void main(String[] args) {
		Food food = new Food();
		food.setName("草");
		Animal animal = new Animal();
		animal.setName("羊");
		animal.setFood(food);
		Animal animal2 = animal.clone();
		System.out.println("animal动物名:"+animal.getName());
		System.out.println("animal食物名:"+animal.getFood().getName());
		System.out.println("animal2动物名:"+animal2.getName());
		System.out.println("animal2食物名:"+animal2.getFood().getName());
	}
}

打印结果是

animal动物名:羊
animal食物名:草
animal2动物名:羊
animal2食物名:草

此时已成功的实现了复制,但是这只是浅复制,引用对象Food并没有被复制。

验证代码

public class TestCopy {
	public static void main(String[] args) {
		Food food = new Food();
		food.setName("草");
		Animal animal = new Animal();
		animal.setName("羊");
		animal.setFood(food);
		Animal animal2 = animal.clone();
		System.out.println("animal动物名:"+animal.getName());
		System.out.println("animal食物名:"+animal.getFood().getName());
		System.out.println("animal2动物名:"+animal2.getName());
		System.out.println("animal2食物名:"+animal2.getFood().getName());
		//改变animal中food对象的值
		food.setName("树叶");
		System.out.println("animal动物名:"+animal.getName());
		System.out.println("animal食物名:"+animal.getFood().getName());
		System.out.println("animal2动物名:"+animal2.getName());
		System.out.println("animal2食物名:"+animal2.getFood().getName());
	}
}

打印结果是

animal动物名:羊
animal食物名:草
animal2动物名:羊
animal2食物名:草
animal动物名:羊
animal食物名:树叶
animal2动物名:羊
animal2食物名:树叶

结果证明改变animal中的引用对象food,同时也改变了animal2中的引用对象food,说明animal和animal2的引用对象food是同一对象。

⑵深复制

要实现深复制,就必须同时复制引用对象,引用对象需实现Cloneable接口,Food修改如下

public class Food implements Cloneable{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Food clone() {
		Food food = null;
		try {
			food = (Food) super.clone(); 
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return food;
	}
}

Animal修改如下

public class Animal implements Cloneable {
	// 动物名
	private String name;
	// 食物
	private Food food;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Food getFood() {
		return food;
	}
	public void setFood(Food food) {
		this.food = food;
	}
	public Animal clone() {
		Animal animal = null;
		try {
			animal = (Animal) super.clone(); 
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		//复制引用对象
		animal.food = food.clone();
		return animal;
	}
}

在clone方法中添加了引用对象的复制

使用上面的main方法测试,打印结果如下

animal动物名:羊
animal食物名:草
animal2动物名:羊
animal2食物名:草
animal动物名:羊
animal食物名:树叶
animal2动物名:羊
animal2食物名:草

结果证明animal和animal2的引用对象food已经不是同一对象了,此时成功地实现了深复制。

2.使用序列化(Serializable接口)实现对象的复制

使用Cloneable接口每个类都需要写clone方法,工作量是很大的,我们可以使用序列化来实现对象的拷贝,这需要对象实现java.io.Serializable接口。

将上面的Animal和Food修改一下

import java.io.Serializable;
public class Food implements Serializable{
	private static final long serialVersionUID = 6466656398591229036L;
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
import java.io.Serializable;
public class Animal implements Serializable {
	private static final long serialVersionUID = -8424013303049171827L;
	// 动物名
	private String name;
	// 食物
	private Food food;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Food getFood() {
		return food;
	}
	public void setFood(Food food) {
		this.food = food;
	}
}

再写一个复制的工具类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class CopyUtil {
	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T obj) {
		T cloneObj = null;
		ByteArrayOutputStream baos = null;
		ByteArrayInputStream bais = null;
		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;
		try {
			// 序列化
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			oos.writeObject(obj);
			// 反序列化,生成新对象
			bais = new ByteArrayInputStream(
					baos.toByteArray());
			ois = new ObjectInputStream(bais);
			cloneObj = (T) ois.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			try {
				if(oos!=null){
					oos.close();
				}
				if(baos!=null){
					baos.close();
				}
				if(ois!=null){
					ois.close();
				}
				if(bais!=null){
					bais.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return cloneObj;
	}
}

测试代码

public class TestCopy {
	public static void main(String[] args) {
		Food food = new Food();
		food.setName("草");
		Animal animal = new Animal();
		animal.setName("羊");
		animal.setFood(food);
		Animal animal2 = CopyUtil.clone(animal);
		System.out.println("animal动物名:"+animal.getName());
		System.out.println("animal食物名:"+animal.getFood().getName());
		System.out.println("animal2动物名:"+animal2.getName());
		System.out.println("animal2食物名:"+animal2.getFood().getName());
		//改变animal中food对象的值
		food.setName("树叶");
		System.out.println("animal动物名:"+animal.getName());
		System.out.println("animal食物名:"+animal.getFood().getName());
		System.out.println("animal2动物名:"+animal2.getName());
		System.out.println("animal2食物名:"+animal2.getFood().getName());
	}
}

打印结果如下

animal动物名:羊
animal食物名:草
animal2动物名:羊
animal2食物名:草
animal动物名:羊
animal食物名:树叶
animal2动物名:羊
animal2食物名:草

利用序列化成功的实现了深复制。

到此这篇关于Java实现对象复制的方法实例的文章就介绍到这了,更多相关Java对象复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot整合mqtt实现消息订阅和推送功能

    springboot整合mqtt实现消息订阅和推送功能

    mica-mqtt-client-spring-boot-starter是一个方便、高效、可靠的MQTT客户端启动器,适用于需要使用MQTT协议进行消息通信的Spring Boot应用程序,这篇文章主要介绍了springboot整合mqtt实现消息订阅和推送功能,需要的朋友可以参考下
    2024-02-02
  • Java之CMS和G1垃圾回收过程的异同说明

    Java之CMS和G1垃圾回收过程的异同说明

    CMS垃圾回收器主要基于并发-清理算法,目的是减少停顿时间,通过四个主要阶段进行垃圾回收:初始标记、并发标记、重新标记和并发清理,G1垃圾回收器采用标记-整理算法,是JDK9后的默认垃圾收集器,设计为全功能全代收集器
    2024-09-09
  • 解决IDEA2020控制台乱码的方法

    解决IDEA2020控制台乱码的方法

    这篇文章主要介绍了解决IDEA2020控制台乱码的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    这篇文章主要介绍了鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • SpringSecurity 用户帐号已被锁定的问题及解决方法

    SpringSecurity 用户帐号已被锁定的问题及解决方法

    这篇文章主要介绍了SpringSecurity 用户帐号已被锁定,本文给大家分享问题原因及解决方式,需要的朋友可以参考下
    2023-12-12
  • SpringMVC实现参数校验配置方法

    SpringMVC实现参数校验配置方法

    这篇文章主要介绍了SpringMVC实现参数校验的配置方式,Spring MVC会抛出MethodArgumentNotValidException异常,并将错误信息绑定到相应的字段上,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • 你必须得会的SpringBoot全局统一处理异常详解

    你必须得会的SpringBoot全局统一处理异常详解

    程序在运行的过程中,不可避免会产生各种各样的错误,这个时候就需要进行异常处理,本文主要为大家介绍了SpringBoot实现全局统一处理异常的方法,需要的可以参考一下
    2023-06-06
  • java输出1~100之间的全部素数的5种方式总结

    java输出1~100之间的全部素数的5种方式总结

    这篇文章主要介绍了java输出1~100之间的全部素数的5种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 聊聊springmvc中controller的方法的参数注解方式

    聊聊springmvc中controller的方法的参数注解方式

    本篇文章主要介绍了聊聊springmvc中controller的方法的参数注解方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 你知道JVM中GC Root对象有哪些吗

    你知道JVM中GC Root对象有哪些吗

    这篇文章主要介绍了你知道JVM中GC Root对象有哪些,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论