zoukankan      html  css  js  c++  java
  • [改善Java代码]警惕数组的浅拷贝

    建议62:警惕数组的浅拷贝

    一、分析 

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

    二、场景 

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

     1 import org.apache.commons.lang3.builder.ToStringBuilder;
     2 
     3 public class Client{ 
     4     public static void main(String[] args){ 
     5         //气球的数量 
     6         int ballonNum = 7; 
     7         //第一个箱子 
     8         Ballon[] box1 = new Ballon[ballonNum]; 
     9         //初始化第一个箱子 
    10         for(int i = 0; i < ballonNum; i++){ 
    11             box1[i] = new Ballon(Color.values()[i],i); 
    12         } 
    13 
    14         //第二个箱子的小球是拷贝的第一个箱子里的 
    15         Ballon[] box2 = Arrays.copyOf(box1,box1.length); 
    16         //修改最后一个气球的颜色 
    17         box2[6].setColor(Color.Blue); 
    18         //打印出第一个箱子中的气球颜色 
    19         for(Ballon b:box1){ 
    20             System.out.println(b); 
    21         } 
    22     } 
    23 } 
    24 
    25 //气球的颜色 
    26 enum Color{ 
    27     Red,Orange,Yellow,Green,Indigo,Blue,Violet; 
    28 } 
    29 
    30 //气球 
    31 class Ballon{ 
    32     //编号 
    33     private int id; 
    34     //颜色 
    35     private Color color; 
    36 
    37     public int getId() {
    38         return id;
    39     }
    40 
    41     public void setId(int id) {
    42         this.id = id;
    43     }
    44 
    45     public Color getColor() {
    46         return color;
    47     }
    48 
    49     public void setColor(Color color) {
    50         this.color = color;
    51     }
    52 
    53     public Ballon(Color _color,int _id){ 
    54         color = _color; 
    55         id = _id; 
    56     } 
    57 
    58     /*id、color的getter/setter方法省略*/ 
    59     //apache-common包下的ToStringBuilder重写toString方法 
    60     public String toString(){ 
    61         return new ToStringBuilder(this).append("编号",id).append("颜色",color).toString(); 
    62     } 
    63 }

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

    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拷贝,然后转换成集合,简单便捷!但是,非常遗憾,这里我们有撞到浅拷贝的 枪口上了!!!!

    三、建议 

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

  • 相关阅读:
    使用过的一些前端工具
    文档和元素中与几何形状和滚动相关的属性和方法
    文档元素选取和遍历中的一些容易忘记的概念
    只存在于理想中的客户端JavaScript时间线
    JavaScript函数代码和执行上下文--ECMA-262-5
    JavaScript中的闭包
    Git Note
    HDOJ 4463 Outlets 最短路
    HDOJ 4548 美素数
    HDOJ 2544 最短路
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5422216.html
Copyright © 2011-2022 走看看