0

試験問題でした。幸いなことに、私は正しい答えを選びましたが、なぜそれが正しいのかはまだわかりません。

このプログラムを考えてみましょう:

class D {
  protected C c;
  public D(C c) {
    this.c = new C(c);
  }
  public C getC() {
    return c;
  }
  public void setC(C c) {
    this.c = c;
  }
}
class C {
  protected String s;
  public C(String s) {
    this.s = s;
  }
  public C(C c) {
    this(c.s);
  }
  public String getS() {
    return s;
  }
  public void setS(String s) {
    this.s = s;
  }

  public static void main(String[] args) {
    C c1 = new C("1");
    C c2 = new C("2");
    D[] d = {
      new D(c1), new D(c1), new D(c2), new D(c2)
    };
    d[0] = d[3];
    c1.setS("3");
    String r = "";
    for (D i: d) {
      r += i.getC().getS();
    }
    System.out.println(r);
  }

}

印刷されます2122。ただし、私は期待し2322ています (コードを実行すると明らかに間違っています)。その背後にある私の理由:

main メソッドの 3 行目で、Dget の 4 つのインスタンスが初期化されます。のコンストラクタはD、 の新しいインスタンスを作成しますC。のインスタンスにCString、メモリ内のスポットを指す変数があります。ここで、 のオブジェクトのインスタンス変数c、それと呼びましょうはインスタンス変数 (タイプ ) を持ち、 の変数と同じメモリを指している と呼びましょう。c3d[1]Strings3String s1c1

したがって、 を変更すると、メモリ内の同じ場所を指しているため、s1の値も変更されることが予想されます。s3

補足として、 のコンストラクターを変更するとD、以下を参照してください2322。代わりに取得されます。c3の変数がd[1]のメモリ位置を直接指しているので、これは私が期待することですc1

public D(C c) {
  this.c = c;
}

これまでの説明に関する私の考え(間違っている可能性があります):

  1. インスタンス変数s1/を初期化するs3と、新しいオブジェクトが作成されます (これまでのところ、コンストラクターがそのように見えるため、プール内Stringを指していると想定していました)"1"StringC
  2. を変更するs1と、そのポインターはプール内にリダイレクトさ"3"Stringます。"1"プールに入るよりも"3"

誰でもこの動作を説明できますか? 私の(誤った)推論の誤りは何ですか?

4

1 に答える 1