[???] /
[Java FAQ] / [S027]
S027: オブジェクトのコピー - clone
[S027 Q-01]
オブジェクトのコピーは
dst = src
ではいけないのでしょうか?
[S027 A-01]
だめですね。
上記の操作によって値がコピーされるのはプリミティブ型(primitive)のみ
です。
Java では、以下のような2つの異なるタイプが提供されています。
・プリミティブ(ビルトイン)型
・参照(オブジェクト)型
プリミティブ型には以下のものがあります。
boolean, char, byte, short, int, long, float, double
Java では通常のオブジェクトは上記参照型として定義されます。
すなわち、オブジェクトを格納する変数は全て実体ではなく参照を保持
しているということです。
プリミティブタイプの代入操作では、元の値が代入先に転記されますので
完全な意味でのコピー操作となります。
参照タイプの代入操作も、変数の値自体は完全にコピーされますがその意味する
所は参照のコピーとなりますので、それぞれの変数が指し示すオブジェクトの
実体は同一のものとなります。
上記操作後においても dst 及び src は単に同一のオブジェクトを指し示す
異なった変数となるだけですので、一方に対する操作は、もう一方にも反映
されることになります。
[S027 Q-02]
オブジェクトをコピーしたいのですが?
[S027 A-02]
Object#clone() メソッドを使用します。
[S027 Q-03]
オブジェクトのコピー時に
CloneNotSupportedException
が発生するのですが?
[S027 A-03]
コピー元のオブジェクトが Cloneable インターフェースを実装していない
からです。
特定のオブジェクトに対して clone() メソッドによるコピーを行う必要が
ある場合は、対象となるオブジェクトに java.lang.Cloneable を実装しな
ければなりません。
[S027 Q-04]
コピー元のオブジェクトを変更すると、コピー先のオブジェクトも変更され
てしまいます。なぜ?
[S027 A-04]
clone() メソッドによるコピーでは、内部に保持されているオブジェクトは
複製されないためです。
たとえば、
class Sample implements Cloneable {
StringBuffer buffer;
}
このようなクラスにおいては buffer 変数は、StringBuffer のインスタンス
の参照を保持する器となります。
Sample.clone() によって複製されるインスタンスが保持する buffer 変数は
コピー元と同一な値を持ちますから、同じ StringBuffer のインスタンスへ
の参照となります。
したがって、コピー元の buffer に対する変更は、コピー先の buffer にも
反映されるように見えるのです。
@see System#arraycopy
[S027 Q-05]
オブジェクトを内部に含まれるオブジェクトまで完全に複製したいのですが?
[S027 A-05]
clone() メソッドを再実装して実現します。
実装の詳細は、対象とするオブジェクトの構造に依存するため一般的な方法
はありません。
オブジェクトが java.lang.Serializable インターフェースを実装している
場合は、ObjectOutputStream ObjectInputStream を用いることで完全な複製
を作成することもできます。
以下 targetObject を複製して copyObject に取得する際のサンプルコード
です。(例外処理は除く)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(targetObject);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
copyObject = bis.readObject();
contributor: Osamu Hasegawa, Tsuyoshi Tsuhtan Sato
コメントの送り先 Java FAQ BBS