java的深拷贝和浅拷贝了解一下

简介: java的深拷贝和浅拷贝了解一下

我们知道拷贝就是生成一个新对象和原对象一模一样,但是拷贝也是分方式和程度的,我们来看一下什么是浅拷贝什么是深拷贝

浅拷贝

在Java中,java.lang.Object类的clone()方法用于克隆(浅拷贝,属性的指向是相同的)。
该方法创建一个对象的副本,并通过逐字段分配在其上对其进行调用并返回该对象的引用。
要实现浅拷贝需要实现Cloneable接口,该接口里面没有任何方法,它指向的是java.lang.Object类的clone()

protected native Object clone() throws CloneNotSupportedException;

它是一个native方法,由C/C++实现
我们看看例子,理解下它为啥叫浅拷贝
首先有一个字典对象类,它实现了克隆的接口

@Data
class Dictionary implements Cloneable {

   private String name;

   private List<String> words;

   @Override
   public Object clone() {
       try {
           return super.clone();
       } catch (CloneNotSupportedException e) {
           e.printStackTrace();
       }
       return null;
   }
}
public static void shallowCopy() {
       Dictionary dictionary1 = new Dictionary();
       dictionary1.setName("汉语词典");
       dictionary1.setWords(new ArrayList<String>() {{
           add("你好");
           add("浅拷贝");
       }});
       Dictionary dictionary2 = (Dictionary) dictionary1.clone();
       System.out.println(dictionary1 == dictionary2);
       dictionary2.getWords().add("新词语");
       System.out.println("dictionary1: " + dictionary1.toString());
       System.out.println("dictionary2: " + dictionary2.toString());

       dictionary1.setName("新名字");
       System.out.println("dictionary1: " + dictionary1.toString());
       System.out.println("dictionary2: " + dictionary2.toString());
   }

运行结果:

false
dictionary1: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])
dictionary2: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])
dictionary1: Dictionary(name=新名字, words=[你好, 浅拷贝, 新词语])
dictionary2: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])

从结果上我们知道dictionary1,dictionary2不是指向的同一个对象,确实创建了两个对象,但是当第二个对象属性被修改时,第一个对象也跟着变了。
验证了我们之前说的浅拷贝,两个对象的属性指向的是堆中相同的对象。

深拷贝

深拷贝相对于浅拷贝来说就是属性也是新的对象,我们可以将对象的每一个属性也实现cloneable接口,就可以达到深拷贝的效果。我们也可以使用序列化反序列化来实现深拷贝。
首先将Dictionary实现Serializable接口

@Data
class Dictionary implements Cloneable, Serializable {

    private String name;

    private List<String> words;

    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
private static void deepCopy() throws IOException, ClassNotFoundException {
        Dictionary dictionary1 = new Dictionary();
        dictionary1.setName("汉语词典");
        dictionary1.setWords(new ArrayList<String>() {{
            add("你好");
            add("浅拷贝");
        }});

        Dictionary dictionary2 = null;

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(dictionary1);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
        dictionary2 = (Dictionary) ois.readObject();

        // 测试方法没关闭流 实际项目记得关闭流
        System.out.println(dictionary1 == dictionary2);
        dictionary2.getWords().add("新词语");
        System.out.println("dictionary1: " + dictionary1.toString());
        System.out.println("dictionary2: " + dictionary2.toString());
    }

运行结果

false
dictionary1: Dictionary(name=汉语词典, words=[你好, 深拷贝])
dictionary2: Dictionary(name=汉语词典, words=[你好, 深拷贝, 新词语])

我可以看到不管是对象还是它的属性都是独立的,这就是深拷贝。

相关文章
|
6月前
|
Java
Java的浅拷贝与深拷贝
Java的浅拷贝与深拷贝
53 0
|
6月前
|
Java Apache
Java中的深拷贝与浅拷贝
Java中的深拷贝与浅拷贝
45 0
|
5月前
|
Java
“深入探讨Java中的对象拷贝:浅拷贝与深拷贝的差异与应用“
“深入探讨Java中的对象拷贝:浅拷贝与深拷贝的差异与应用“
|
5月前
|
存储 Dubbo Java
一篇文章讲明白Java的深拷贝和浅拷贝
一篇文章讲明白Java的深拷贝和浅拷贝
51 0
|
6月前
|
Java
【JAVA面试题】什么是深拷贝?什么是浅拷贝?
【JAVA面试题】什么是深拷贝?什么是浅拷贝?
|
Java
Java深拷贝和浅拷贝Map对象
Java深拷贝和浅拷贝Map对象
196 0
|
Java
【java面试题】- java深拷贝和浅拷贝区别?什么是引用拷贝?
java深拷贝和浅拷贝区别?什么是引用拷贝?
87 0
Java 最常见的面试题:深拷贝和浅拷贝区别是什么?
Java 最常见的面试题:深拷贝和浅拷贝区别是什么?
|
Java
【Java】深拷贝和浅拷贝,Cloneable接口
【Java】深拷贝和浅拷贝,Cloneable接口
201 0
【Java】深拷贝和浅拷贝,Cloneable接口
Zp
|
Java
JAVA深拷贝和浅拷贝
JAVA深拷贝和浅拷贝
Zp
97 0