java如何实现深拷贝
Java浅拷贝
- 浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
Java深拷贝
- 深拷贝复制变量值,对于引用数据,则递归至基本类型后,再复制。深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。深拷贝相比于浅拷贝速度较慢并且花销较大。
Java浅拷贝和深拷贝的区别是什么?
- 通俗来讲浅拷贝的复制其引用,当引用指向的值改变时也会跟着变化;而深拷贝则是与原来的对象完全隔离,互不影响。
深拷贝的实现方法主要有两种:
-
(1) 通过重写clone方法来实现深拷贝(实现Cloneable接口)
-
慎用 Object 的 clone 方法来拷贝对象。
-
说明: 对象的 clone 方法默认是浅拷贝,若想实现深拷贝需要重写 clone 方法实现属性对象的拷贝。
-
与通过重写clone方法实现浅拷贝的基本思路一样,只需要为对象图的每一层的每一个对象都实现Clonneable接口并重写clone方法,最后在最顶层的类的重写的clone方法中调用所有的clone方法即可实现深拷贝。简单的说就是“每一层的每个对象都进行浅拷贝=深拷贝。
-
(2)推荐: 通过对象序列化实现深拷贝(实现Serializable接口)
-
虽然层次调用clone方法可以实现深拷贝,但是显然代码量实在太大。特别对于属性数量比较多、层次比较深的类而言,每个类都要重写clone方法太过繁琐。
-
将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。
-
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class ObSriaInOut { public static void main(String[] args) throws IOException, ClassNotFoundException { Persen p = in (); Persen p2 = out(); System.out.println(p); System.out.println(p2); } public static Persen out() throws IOException, FileNotFoundException { //创建对象输出流,在使用对象输出流时必须进行对象序列化,否则会报错java.io.NotSerializableException ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f:\\person.bin", false)); //床架你一个persn对象 Persen p = new Persen("张大", 22, 5000); //写出对象流 oos.writeObject(p); //关闭流 oos.flush(); oos.close(); return p; } public static Persen in () throws IOException, FileNotFoundException, ClassNotFoundException { //创建对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f:\\person.bin")); //读取对象流 Persen p = (Persen) ois.readObject(); ois.close(); System.out.println(p.toString()); return p; } }
-
persen类
-
package com.javabase.obj.serializable; import java.io.Serializable; public class Persen implements Serializable { private String name; private double sal; private int age; public Persen() { super(); } //构造方法用于初始化成员参数 public Persen(String name, double sal, int age) { super(); this.name = name; this.sal = sal; this.age = age; } @Override public String toString() { return this.name + "---" + this.age + "---" + this.sal; } }