Java 浅拷贝和深拷贝|Java 开发实战

本文正在参加「Java主题月 – Java 开发实战」,详情查看 活动链接

开篇

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

在开发中你有没有遇到过一些关于集合复制的问题?

普通的集合复制只是将内存中栈的地址块拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域。所以当拷贝的集合修改了自己集合对象内的数据时,源集合对象也随之改变了,这样的效果我们称之为Java集合对象的浅复制(即只是在栈中拷贝了,而堆中的数据并没有拷贝。)

而深复制则是同时将栈中和堆中的数据进行拷贝,这样其拷贝的集合和被拷贝的集合就没有任何关系了。

案例演示

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Demo {  
    private int  demoValue;  
}
复制代码

试验一下浅复制:

@Test  
public void testDemoCopy() {  
    // 这里我创建了一个源集合
    ArrayList<Demo> sourceCollection = new ArrayList<Demo>();  
    // 这里我向sourceCollection添加了一些对象
    sourceCollection.add(new Demo(1));  
    sourceCollection.add(new Demo(2));  
    // 这里我创建了一个新的空集合 
    ArrayList<Demo> newCollection = new ArrayList<Demo>();  
    newCollection.addAll(sourceCollection);  
    // 现在我修改了新集合中的一些对象
    newCollection.get(0).setDemoValue(3);  
    // 现在我们验证它在源集合中是什么  
    for(Demo demo : sourceCollection){  
        System.out.println(demo.getDemoValue());  
    }   
    // 断言验证源Collection是否被修改.  
    Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);  
}
复制代码

很明显,newCollection中改变的Demo对象在SourceCollection中也跟着改变了,这说明两个集合中的Demo对象是同一个对象。这也是浅复制所存在的弊端。

那么如何将两个集合独立开来呢,即如何进行深度复制?

试验一下深复制:

首先我们先对Demo类作一下处理,使其实现Cloneable接口,并重写它的clone方法

protected Demo clone() throws CloneNotSupportedException {             
   return (Demo)super.clone();  
}
复制代码

测试类如下

@Test  
public void testCopyDeep() throws Exception{  
    ArrayList<Demo> sourceCollection = new ArrayList<Demo>();  
    sourceCollection.add(new Demo(1));  
    sourceCollection.add(new Demo(2));    
      
    ArrayList<Demo> newCollection = new ArrayList<Demo>();  
    for(Demo demo : sourceCollection){  
        // 这里是重点
        newCollection.add(demo.clone());  
    }  
    newCollection.get(0).setDemoValue(3);  
    for(Demo demo : sourceCollection){  
        System.out.println(demo.getDemoValue());  
    }  
    Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);  
}
复制代码

最后我们来观察一下结果:两个集合各自独立,谁修改都不会互相影响对象

另一种快速copy集合的写法

现在很多人都用jdk8以上的版本了,那么上面这种复制集合的写法就显得有点臃肿了,可以使用java lambda表达式来进行语义上的优化,如下所示:

图片[1]-Java 浅拷贝和深拷贝|Java 开发实战-一一网

关注+点赞?收藏❤️不迷路

文章每周持续更新,可以微信搜索「 十分钟学编程 」第一时间阅读和催更,如果这个文章写得还不错,觉得有点东西的话
各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享