警惕数组的浅拷贝

        有这样一个例子,第一个箱子有赤橙黄绿青蓝紫7色气球,现在希望第二个箱子的气球和第一个箱子一样,只是最后一个气球是蓝色的。对于这个问题,我们自然会想到拷贝的方法来解决问题。

      附代码:

import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;

public class Test4 {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        int ballonNum = 7;
        Balloon[] box1 = new Balloon[ballonNum];
        for (int i = 0; i < ballonNum; i++) {
            box1[i] = new Balloon(Color.values()[i], i);
        }
        Balloon[] box2 = Arrays.copyOf(box1, box1.length);
        box2[6].setColor(Color.Blue);
        for (Balloon b : box1) {
            System.out.println(b);
        }
    }

}

enum Color {
    Red, Orange, Yellow, Green, Indigo, Blue, Violet;
}

class Balloon {
    private int id;
    private Color color;

    public Balloon(Color _color, int _id) {
        color = _color;
        id = _id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public String toString() {
        return new StringBuffer().append("编号:" + id + "颜色:" + color + ";")
                .toString();

    }
}

现在我们看看通过拷贝后的第一个箱子的气球的颜色是什么样子的:

我们看到最后一个气球变成了blue。我们只希望第二个箱子改变最后一个气球的颜色,这和我们预想的不一样。到底哪地方出了问题?

        我们知道,通过copyOf方法产生的数组是一个浅拷贝,拷贝有个很重要的规则(数组的clone方法也是与此相同的,同样是浅拷贝):基本类型都是直接拷贝值,其他都是拷贝引用地址。问题找到了(调用了相同的引用地址),那么修改的方法可以如下:

import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;

public class Test4 {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        int ballonNum = 7;
        Balloon[] box1 = new Balloon[ballonNum];
        for (int i = 0; i < ballonNum; i++) {
            box1[i] = new Balloon(Color.values()[i], i);
        }
        Balloon[] box2 = Arrays.copyOf(box1, box1.length);
        //box2[6].setColor(Color.Blue);
        Balloon bb=new Balloon(Color.Blue,6);
        box2[6]=bb;
        for (Balloon b : box1) {
            System.out.println(b);
        }

    }

}

enum Color {
    Red, Orange, Yellow, Green, Indigo, Blue, Violet;
}

class Balloon {
    private int id;
    private Color color;

    public Balloon(Color _color, int _id) {
        color = _color;
        id = _id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public String toString() {
        return new StringBuffer().append("编号:" + id + "颜色:" + color + ";")
                .toString();

    }
}

第一个箱子气球颜色为:

 

这下就对了。

时间: 2024-11-14 20:10:20

警惕数组的浅拷贝的相关文章

数组的 浅拷贝 &amp; 深拷贝

继续不多bb,直接上代码: 含值类型的元素的假拷贝: let obj = [1, 2] let copyFake = obj // let copyFake = [...obj] copyFake[1] = 20 console.log(obj[1]) // 20 console.log(copyFake[1]) // 20 含值类型的元素的浅拷贝: let obj = [1, 2] let copyShallow = obj.slice() // let copyShallow = [...o

改善java程序的151个建议--数组和集合

60.性能考虑,数组是首选,在基本类型处理方面,数组还是占优势的,而且集合类的底层也都是通过数组实现,建议在性能要求较高的场景中使用数组替代集合. 61.如果有必要,使用变长数组:我们可以通过对数组扩容"婉转"地解决数组扩容问题,下面采用的是Arrays数组工具类的copyOf方法,产生了一个newLen长度的新数组,并把原有的值拷贝了进去,之后就可以对超长的元素进行赋值了 62.警惕数组的浅拷贝 Person[] p=new Person[5]; Person[] p2=Arrays

《编写高质量代码:改善Java程序的151个建议》笔记

To fight the unthinkable,you have to be willing to do the unthinkable. 不要在循环中使用try catch,应该放在循环的外面. One Line 务必让常量的值在运行期间保持不变. 保证三元操作符中的两个操作类型一致. 反序列化时构造方法不会执行. 在序列化类中,不使用构造方法为final变量赋值. 避免为final变量复杂赋值. 发布应用系统时,禁止使用类文件替换方式,整体WAR包发布才是万全之策. 包装类型参与运算时,要

程序员小习惯

第一章  Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符的类型务必一致: (不一致会导致自动类型转换,类型提升int->float->double等). 建议4:避免带有变长参数的方法重载: (变长参数的方法重载之后可能会包含原方法). 建议5:别让null值和空值威胁到变长方法: (两个都包含变长参数的重载方法,当变长参数部分空值,或者为null值时

编写高质量代码:改善Java程序的151个建议-学习笔记

java中通用的方法和准则 1.不要让常量和变量中出现易混淆的字母 比如: long i = 1l; 别人很难一下子看清楚是11还是1l,所以应该这样写1L. 命名规范: 1.包名全部小写 2.类名首字母大写 3.方法名称,首字母小写,后面单词首字母大写 4.常量要用大写,并且用下划线隔开 5.变量要用小写 2.莫让常量蜕变成变量 interface Const { public static final int RANDOM_NUM = new Random().nextInt(10); }

编写高质量JAVA程序代码的建议

--------------------------------------------------------------------------------------------------- 前言:原著<改善JAVA程序的151个建议>有151个建议,我在拜读的过程根据自己的理解合并了其中的几个,并将每个建议的核心要义进行了一次纯手工提炼,以方便想阅读这本书的同行能够更快的掌握这本书的所有核心内容. -------------------------------------------

JS中实现数组和对象的深拷贝和浅拷贝

数组的拷贝 > 数组的深拷贝,两层 var arr = [[1,2,3],[4,5,6],[7,8,9]]; var arr2 = []; 循环第一层数组 for(var i=0,len=arr.length;i<len;i++){ 循环第二层数组 for(var k=0,lens=arr[i].length;k<lens;k++){ 把每一个数组的内容添加到数组2中 arr2.push(arr[i][k]); } } console.log(arr2); //[1, 2, 3, 4,

转载--编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议65~69)

阅读目录 建议65:避开基本类型数组转换列表陷阱 建议66:asList方法产生的List的对象不可更改 建议67:不同的列表选择不同的遍历算法 建议68:频繁插入和删除时使用LinkList 建议69:列表相等只关心元素数据 回到顶部 建议65:避开基本类型数组转换列表陷阱 我们在开发中经常会使用Arrays和Collections这两个工具类和列表之间转换,非常方便,但也有时候会出现一些奇怪的问题,来看如下代码: 1 public class Client65 { 2 public stat

Javascript学习之深拷贝和浅拷贝详解

在JavaScript 中,存在着这样的两种拷贝方式.分别是:深拷贝和浅拷贝,这两种拷贝在实际中非常的常见,如果读者是一个阅读源码的爱好者,相信多多少少对深拷贝和浅拷贝有所了解.本文和大家分享的就是深拷贝和浅拷贝相关内容,一起来看看吧,希望对大家 学习javascript有所帮助. 一.浅拷贝 浅拷贝在现实中最常见的表现在赋值上面,例如 <!DOCTYPE html> <html lang="en"> <head> <meta charset=