为什么对 v、w 的赋值行为不同?

Why do the assignments to v, w behave differently?

我希望在 v 上有一个浅拷贝并输出 701 801,但我看到了 700 801。我找不到很好的解释。如果 w 是浅拷贝,为什么 v 不是? Integer 是否分配了 Integer "rebox"?

class Scalar {
    Integer w;
    public String toString() { return String.valueOf( w ); }
}

public class Demo {
    public Integer v;
    public Scalar scal;

    Demo shallowCopy() {
        Demo scopy = new Demo();
        scopy.v = this.v;  // <- Given this I would 701 from 
        scopy.scal = this.scal;
        return scopy;
    }

    public String toString() { return String.valueOf(v) + " " + scal.toString();  }

    public static void main( String[] args ) {
        Demo d1 = new Demo();
        d1.v = 700;
        d1.scal = new Scalar();
        d1.scal.w = 800;
        Demo d2 = d1.shallowCopy();
        d2.v = 701;
        d2.scal.w = 801;
        System.out.println( d1 );
    }
}

d2.v = 701; 替换整个 Integer.

您的浅拷贝复制了对 d1 持有的 Integer 对象的引用,因此 d2.v 引用了 Integer 对象本身,而不是对 d1.v.

另一方面,d2.scal 没有被替换。因此,d1.scal 等于 d2.scal 因为它们是完全相同的对象。如果您更改 scal.w,它会更改该对象中的值,d1.scald2.scal 都会更改。同时,覆盖 d2.v 会更改引用,但不会更改 d2.v 本身指向的对象,因此不会更改 d1.v.