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对象复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码
这篇文章主要介绍了鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2021-01-01SpringSecurity 用户帐号已被锁定的问题及解决方法
这篇文章主要介绍了SpringSecurity 用户帐号已被锁定,本文给大家分享问题原因及解决方式,需要的朋友可以参考下2023-12-12聊聊springmvc中controller的方法的参数注解方式
本篇文章主要介绍了聊聊springmvc中controller的方法的参数注解方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-10-10
最新评论