1. ホーム
  2. java

Javaでオブジェクトを複製する

2023-08-26 09:32:51

質問

Javaで変数を変更しても、その元になった変数は変更されないことを知りました。

int a = new Integer(5);
int b = a;
b = b + b;
System.out.println(a); // 5 as expected
System.out.println(b); // 10 as expected

オブジェクトについても同じようなことを想定しました。このクラスについて考えてみましょう。

public class SomeObject {
    public String text;

    public SomeObject(String text) {
        this.setText(text);
    }

    public String getText() {
        return text;
    }   

    public void setText(String text) {
        this.text = text;
    }
}

このコードを試した後、私は混乱しました。

SomeObject s1 = new SomeObject("first");
SomeObject s2 = s1;
s2.setText("second");
System.out.println(s1.getText()); // second as UNexpected
System.out.println(s2.getText()); // second as expected

なぜ、どちらかのオブジェクトを変更すると、もう一方のオブジェクトに影響を与えるのか、説明してください。変数textの値は、両方のオブジェクトのメモリ上の同じ場所に格納されていることは理解しています。

変数の値は独立しているのに、オブジェクトの値は相関しているのはなぜでしょうか?

また、単純な代入ではうまくいかない場合、どのようにSomeObjectを複製するのでしょうか?

どのように解決するのですか?

Javaではすべての変数が 参照 . ですから

SomeClass s2 = s1;

を指定するだけです。 s2 と同じオブジェクトに s1 が指すのと同じオブジェクトに代入しています。実際には、参照 s1 の値 (これは SomeClass のインスタンスを指している)参照 s1 の値を s2 に代入していることになります。 を変更した場合 s1 , s2 も同様に修正されます。 (も修正されます(同じオブジェクトを指しているため)。

例外として、プリミティブ型があります。 int, double, float, boolean, char, byte, short, long . これらは値で保存されます。ですから = を使用する場合、値を代入するだけで、同じオブジェクトを指すことはできません(参照ではないため)。これは次のことを意味します。

int b = a;

の値を設定するだけです。 b の値を a . を変更した場合 a , b は変わりません。

結局のところ、すべては値による代入であり、それは参照の値であって、オブジェクトの値ではありません(上記のようにプリミティブ型の例外を除いて)。

ですから、あなたの場合、コピーを作るなら s1 をコピーしたい場合は、このようにします。

SomeClass s1 = new SomeClass("first");
SomeClass s2 = new SomeClass(s1.getText());

あるいは、コピーコンストラクタを SomeClass に追加して、インスタンスを引数として受け取り、それを自分自身のインスタンスにコピーすることもできます。

class SomeClass {
  private String text;
  // all your fields and methods go here

  public SomeClass(SomeClass copyInstance) {
    this.text = new String(copyInstance.text);
  }
}

これで、かなり簡単にオブジェクトをコピーすることができます。

SomeClass s2 = new SomeClass(s1);