Java复制理解

时间:2013-05-27 07:16:16

标签: java

在测试代码后(见下文),我发现我不了解一些基本原理。

A类。

class A {

    private String s;
    private int[] array;
    private B b;

    public A(String s, int[] array, B b) {
        this.s = s;
        this.array = array;
        this.b = b;
    }
}

B类。

class B {

    public int t;

    public B(int t) {
        this.t = t;
    }

}

我认为A a = new A(s, array, b);后我所做的任何更改都会影响a。请勿a以及变量sarrayb的所有字段引用同一个对象吗?

    String s = "Lorem";
    int array[] = new int[] {
            10, 20, 30
    };
    B b = new B(12);
    A a = new A(s, array, b);
    s = "Dolor";
    array = new int[] {
            23
    };
    b = new B(777); // Initialized with a new value, a.b keeps the old one. Why?
    System.out.println(a);

输出。

String Lorem
Array [10, 20, 30]
B 12

关于这一点。

B b2 = new B(89);
B b3 = b2;
System.out.println(b3);
b2 = null;
System.out.println(b3); // b2 initialized with null, b3 keeps the old one. Why?

输出。

89
89

但是,如果我有两个列表,则表明它们都引用了同一个对象。

    ArrayList<String> first = new ArrayList<String>();
    first.add("Ipsum");
    ArrayList<String> second = new ArrayList<String>();
    second = first;
    first.add("The Earth");
    System.out.println(second);  

输出。

[Ipsum, The Earth]

4 个答案:

答案 0 :(得分:4)

区别在于分配修改

赋值(=)使变量指向其他内容,因此这不会更改基础数据。因此,指向相同数据的任何其他变量都不会改变。

修改(几乎除=之外的任何内容)不会改变变量指向的内容,它只是修改底层对象。因此,指向相同数据的任何其他变量都会发生变化。

例如:

b = new B(777);是分配,因此只有b更改为指向其他内容。 a.b不会改变。

b2 = null;是分配,因此只有b2更改为指向其他内容。 b3不会改变。

如果您要说b2.t = 5,这将是修改(我们没有为b2分配新值,我们通过更改其中一个成员来修改它),所以{{ 1}}也会改变。

我希望能够解释它。

答案 1 :(得分:1)

没有。问题是,你没有改变a,你正在为s分配一个新值。 S是一个String,它是不可变的,这意味着你永远不能改变s的值。但是,您可以更改S中的引用,这就是您正在做的事情。

答案 2 :(得分:1)

为了让自己更清楚,请尝试以下代码行。

String s = "Lorem";
int array[] = new int[] {10, 20, 30};
B b = new B(12);
//A a = new A(s, array, b);

s = "Dolor";
array = new int[] {23};
b = new B(777);
A a = new A(s, array, b);
System.out.println(a);


ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>();
second = first;
second.add("The Earth");
first.remove("The Earth");
System.out.println("second :"+second);

在创建类A的实例(在调用类A构造函数时)时,将打印String s,数组和对象b所持有的当前值。创建A类实例后,String s,数组和对象b将被称为a.s,a.array等。如果为s,array和b赋值,则不会影响A类实例。

对于数组列表问题,两个数组列表仅引用相同的引用。如果你想要不同的参考,那么这样做......(但总是= assign运算符只会做​​同样的参考)

    ArrayList<String> first = new ArrayList<String>();
    first.add("Ipsum");
    ArrayList<String> second = new ArrayList<String>(first);
    second.add("The Earth");
    System.out.println("first :"+first);        
    System.out.println("second :"+second);     

答案 3 :(得分:0)

感谢Dukeling解释赋值如何与对象和基元一起工作,我在这里添加解释当列表对它们执行操作时如何工作。

当我们考虑在问题中的上述代码中创建的两个数组列表时,变量第一个第二个都指向位于相同的数组对象记忆。

因此,当执行添加操作时,底层对象本身会更新。因此,打印操作会打印第二个数组列表,该列表指向在创建第一个数组列表期间创建的同一个数组列表对象。