提高你的Java代码质量吧:警惕数组的浅拷贝

本文通过一个具体的案例,探讨了在Java中使用数组拷贝时遇到的浅拷贝问题,并提供了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、分析 

在日常工作中,我们会遇见很多数组的拷贝和复制的问题,但是在你使用系统提供的API进行编码的时候,无形中会留下浅拷贝的隐患 

二、场景 

有这样一个例子,第一个箱子里面与赤橙黄绿青蓝紫7色气球,现在希望第二个箱子也放入7个气球,其中最后一个气球改为蓝色,也就是赤橙黄绿青蓝蓝七个气球。 

来看实现 

public class Client{ 
    public static void main(String[] args){ 
        //气球的数量 
        int ballonNum = 7; 
        //第一个箱子 
        Ballon[] box1 = new Ballon[ballonNum]; 
        //初始化第一个箱子 
        for(int i = 0; i < ballonNum; i++){ 
            box1[i] = new Ballon(Color.values()[i],i); 
        } 
 
        //第二个箱子的小球是拷贝的第一个箱子里的 
        Ballon[] box2 = Arrays.copyOf(box1,box1.length); 
        //修改最后一个气球的颜色 
        box2[6].setColor(Color.Blue); 
        //打印出第一个箱子中的气球颜色 
        for(Ballon b:box1){ 
            System.out.println(b); 
        } 
    } 
} 
 
//气球的颜色 
enum Color{ 
    Red,Orange,Yellow,Green,Indigo,Blue,Violet; 
} 
 
//气球 
class Ballon{ 
    //编号 
    private int id; 
    //颜色 
    private Color color; 
 
    public Ballon(Color _color,int _id){ 
        color = _color; 
        id = _id; 
    } 
 
    /*id、color的getter/setter方法省略*/ 
    //apache-common包下的ToStringBuilder重写toString方法 
    public String toString(){ 
        return new ToStringBuilder(this).append("编号",id).append("颜色",color).toString(); 
    } 
} 

第二个箱子的最后一个气球毫无疑问是被修改了蓝色,不过是通过拷贝第一个箱子的气球实现的,那么会对第一个箱子的气球颜色有影响吗?输出结果: 

Balloon@b2fd8f[编号=0,颜色=Red] 

Balloon@a20892[编号=1,颜色=Orange] 

Balloon@158b649[编号=2,颜色=Yellow] 

Balloon@1037c71[编号=3,颜色=Green] 

Balloon@1546e25[编号=4,颜色=Indigo] 

Balloon@8a0d5d[编号=5,颜色=Blue] 

Balloon@a470b8[编号=6,颜色=Blue] 

最后一个气球竟然被修改了。这是为何 

这是典型的浅拷贝(Shallow Clone)问题,通过copyOf()方法产生的数组是一个浅拷贝引用地址。需要说明的是数组的clone()方法也是与此相同,同样是浅拷贝,而且集合的clone()方法也是浅拷贝。这就需要大家多留心了 

问题找到了,解决办法也很简单,遍历box1的每个元素,重新生成一个气球(Ballon)对象,并放置到box2数组中。 

很多地方使用集合(如List)进行业务处理时,比如发觉需要拷贝集合中的元素,可集合没有提供任何拷贝方法,所以干脆使用List.toArray方法转换成数组,然后通过Arrays.copyOf拷贝,然后转换成集合,简单便捷!但是,非常遗憾,这里我们有撞到浅拷贝的枪口上了!!!! 

三、建议 

虽然很多时候浅拷贝可以解决业务问题,但更多的时候会留下隐患,需要我们提防又提防

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值