在Java中,是深度复制还是浅层复制的数组类型的字段?

时间:2014-08-21 00:33:33

标签: java arrays deep-copy shallow-copy

[背景说明:我是一名具有C ++背景的新Java程序员,所以对于如何在Java中传递参数有点困惑。]

在阅读和编写一些代码时,我遇到了以下情况

public class B{
    int[] intArr;
    Vector<String> strVec;

    void mutator(){
        // modifies intArr and strVec
    }
}

public class A{
    B bOfA;

    A(B b){
        bOfA = b;
    }

    void foo(){
        bofA.mutator();
    }
}
A中的

foo()肯定会修改bOfA,但是b,传入的对象呢?它的字段/数据成员也会被修改吗?

字段是浅还是深?

strVec和intArr的处理方式不同,因为strVec是一个容器而inArr是一个数组,它可能被实现为某种指针,因此根据它是浅层还是深层复制而表现完全不同。

谢谢。

使用实际代码进行(后期)更新,并且有点令人惊讶(我假设以C / C ++方式解释的按值传递机制)结果:

import java.util.Vector;

public class B{
    int[] intArr = null;
    Vector<String> strVec = null;
    int x = 0;
    String s = null;

    B(int sz){

        x = 0;
        s = new String("ini");

        intArr = new int[sz];
        strVec = new Vector<String>(sz);

        for (int i=0; i<sz; i++){
            intArr[i] = 0;
            strVec.add( new String("xx") );
        }
    }

    void mutator(){

        x = -1;
        s = new String("mute");

        int sz = intArr.length;
        strVec = new Vector<String>(sz);

        for (int i=0; i<sz; i++){
            intArr[i] = -1;
            strVec.add( new String("aa") );
        }
    }
}


import java.util.Vector;

public class A{

    B bOfA=null;

    A(B b){
        bOfA = b;
    }

    void foo(){
        bOfA.mutator();
    }
}



import java.util.Vector;

public class C{

    public static void main(String[] args){
        B b = new B(3);

        A a = new A(b);

        System.out.println("Contents of B before:");
        System.out.println(b.x);
        System.out.println(b.s);
        for(int i=0; i<3; i++){
            System.out.println(b.intArr[i]);
            System.out.println(b.strVec.elementAt(i));
        }

        a.foo();

        System.out.println("\n\nContents of A:");
        System.out.println(a.bOfA.x);
        System.out.println(a.bOfA.s);
        for(int i=0; i<3; i++){
            System.out.println(a.bOfA.intArr[i]);
            System.out.println(a.bOfA.strVec.elementAt(i));
        }
        System.out.println("\n\nContents of B after:");
        System.out.println(b.x);
            System.out.println(b.s);
        for(int i=0; i<3; i++){
            System.out.println(b.intArr[i]);
            System.out.println(b.strVec.elementAt(i));
        }
    }

}

cygwin的结果:

Contents of B before:
0
ini
0
xx
0
xx
0
xx


Contents of A:
-1
mute
-1
aa
-1
aa
-1
aa


Contents of B after:
-1
mute
-1
aa
-1
aa
-1
aa

3 个答案:

答案 0 :(得分:4)

Java按值传递所有内容。但是,Object的值是引用。

两者数组和Vector都是浅拷贝。

答案 1 :(得分:2)

数组是引用对象。当你分配它们时,根本不会复制它们 - 这类似于在C ++中为数组分配数组。

使用System.arraycopy复制数组时,会执行浅复制。从另一个集合构建集合也会创建一个浅表副本。

注意:与C ++库不同,Java类库使用不可变类。例如,String是不可变的;数字的包装也是如此,例如Integer。不变性使得浅层复制与深层复制的相关性低得多。

另一个注意事项:当您需要同步容器时,应使用Vector<T>;如果您不想同步,请改用ArrayList<T>

答案 2 :(得分:1)

what about b, the object that is passed in? 
Will its fields/data members be modified as well?

由于默认情况下java是按值传递,因此在构造函数中传递的对象是按值传递,但在内部,其对象中的字段将具有引用,因此当您调用bofA.mutator()时{ {1}}字段也会发生变化。

要进行深层复制,您需要复制传递的b对象中的每个字段并使用B b