Object浅拷贝、深拷贝
浅拷贝
值传递,新的内存;引用传递,新的指针
通过构造函数实现浅拷贝
Entity.java
public class Entity { // 两个属性值:分别代表值传递和引用传递 private Attr attr; private String name; public Entity(Attr attr, String name) { this.attr=attr; this.name=name; } // 拷贝构造方法 public Entity(Entity p) { this.name=p.name; this.attr=p.attr; } public void setName(String name) { this.name=name; } public String toString() { return this.name+" "+this.attr; } }
Attr.java
public class Attr { private int attr; public Attr(int attr) { this.attr=attr; } public void setAttr(int attr) { this.attr=attr; } public int getAttr() { return this.attr; } public String toString() { return getAttr() + ""; } }
CopyConstructor.java
/* 拷贝构造方法实现浅拷贝 */ public class CopyConstructor { public static void main(String[] args) { Attr attr = new Attr(20); Entity p1 = new Entity(attr,"爆头哥哥"); Entity p2 = new Entity(p1); System.out.println("p1是" + p1); System.out.println("p2是" + p2); //修改p1的各属性值,观察p2的各属性值是否跟随变化 p1.setName("摇头弟弟"); attr.setAttr(99); System.out.println("修改后的p1是" + p1); System.out.println("修改后的p2是" + p2); } }
运行结果
可以看出,Attr的对象引用传递,所以attr设置了新数字之后,两个Entity对象都变了
通过clone实现值传递
Entity.java
package com.example.spring_demo; class Entity implements Cloneable { // Attr 为类的对象 private String name; private Attr attr; private int length; //构造方法,其中一个参数为类的对象 public Entity(String name, Attr attr, int length) { this.name = name; this.attr = attr; this.length = length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Attr getAttr() { return this.attr; } public void setAttr(Attr attr) { this.attr = attr; } public int getLength() { return this.length; } public void setLength(int length) { this.length = length; } // 重写toString方法 public String toString() { return "姓名是: " + this.getName() + ", 年龄为: " + this.getAttr().toString() + ", 长度是: " + this.getLength(); } // 重写Object类的clone方法 public Object clone() { Object obj = null; // 调用Object类的clone方法,返回一个Object实例 try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } }
ShallowCopy.java
package com.example.spring_demo; /* clone方法实现浅拷贝 */ public class ShallowCopy { public static void main(String[] args) { Attr attr = new Attr(20); Entity entity1 = new Entity("爆头哥哥", attr,175); // 通过调用重写后的clone方法进行浅拷贝 Entity entity2=(Entity)entity1.clone(); System.out.println(entity1.toString()); System.out.println(entity2.toString()); // 尝试修改entity1中的各属性,观察entity2的属性有没有变化 entity1.setName("划水弟弟"); // 改变attr这个引用类型的成员变量的值 attr.setAttr(99); // entity1.setAttr(new Attr(99)); // 使用这种方式修改age属性值的话,entity2是不会跟着改变的。因为创建了一个新的Age类对象而不是改变原对象的实例值 entity1.setLength(216); System.out.println(entity1.toString()); System.out.println(entity2.toString()); } }
深拷贝
深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间
通过clone实现深拷贝
Entity.java
class Entity implements Cloneable{ private String name; private Attr attr; private int length; public Entity(String name,Attr attr,int length) { this.name=name; this.attr=attr; this.length=length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Attr getAttr() { return this.attr; } public void setAttr(Attr attr) { this.attr=attr; } public int getLength() { return this.length; } public void setLength(int length) { this.length=length; } public String toString() { return "姓名是: " + this.getName() + ", 年龄为: " + this.getAttr().toString()+", 长度是: " + this.getLength(); } // 重写Object类的clone方法 public Object clone() { Object obj=null; // 调用Object类的clone方法——浅拷贝 try { obj= super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } Entity entity=(Entity)obj; // 学生类实例的Attr对象属性,调用其clone方法进行拷贝 entity.attr = (Attr)entity.getAttr().clone(); return obj; } }
Attr.java
class Attr implements Cloneable{ private int attr; public Attr(int attr) { this.attr=attr; } public int getAttr() { return attr; } public void setAttr(int attr) { this.attr = attr; } public String toString() { return this.attr+""; } //重写Object的clone方法 public Object clone() { Object obj=null; try { obj=super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } }
DeepCopy.java
/* 层次调用clone方法实现深拷贝 */ public class DeepCopy { public static void main(String[] args) { Attr attr = new Attr(20); Entity entity1 = new Entity("爆头哥哥", attr,175); // 通过调用重写后的clone方法进行浅拷贝 Entity entity2=(Entity)entity1.clone(); System.out.println(entity1.toString()); System.out.println(entity2.toString()); entity1.setName("划水弟弟"); // 改变Attr这个引用类型的成员变量的值 attr.setAttr(99); entity1.setLength(216); System.out.println(entity1.toString()); System.out.println(entity2.toString()); } }
序列化实现深拷贝
Entity.java
import java.io.Serializable; class Entity implements Serializable { private String name; private Attr attr; private int length; public Entity(String name,Attr attr,int length) { this.name=name; this.attr=attr; this.length=length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Attr getAttr() { return this.attr; } public void setAttr(Attr attr) { this.attr = attr; } public int getLength() { return this.length; } public void setLength(int length) { this.length=length; } //设置输出的字符串形式 public String toString() { return "姓名是: "+this.getName()+", 年龄为: "+this.getAttr().toString()+", 长度是: "+this.getLength(); } }
Attr.java
import java.io.Serializable; class Attr implements Serializable { private int attr; public Attr(int attr) { this.attr=attr; } public int getAttr() { return attr; } public void setAge(int age) { this.attr = attr; } public String toString() { return this.attr + ""; } }
DeepCopyBySerialization.java
package com.example.spring_demo; import java.io.*; /* 通过序列化实现深拷贝 */ public class DeepCopyBySerialization { public static void main(String[] args) throws IOException, ClassNotFoundException { Attr attr = new Attr(20); Entity entity1 = new Entity("摇头哥哥",attr,175); //通过序列化方法实现深拷贝 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(entity1); oos.flush(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Entity entity2 = (Entity)ois.readObject(); System.out.println(entity1.toString()); System.out.println(entity2.toString()); System.out.println(); entity1.setName("划水弟弟"); attr.setAge(123); entity1.setLength(216); System.out.println(entity1.toString()); System.out.println(entity2.toString()); } }
运行结果
论读书
睁开眼,书在面前 闭上眼,书在心里
睁开眼,书在面前 闭上眼,书在心里