ぶろぐ

日記です

シャローコピーとディープコピー


Javaで、配列をコピーしたい場合の方法は4つ

配列とかをループでまわして捜査することを、イテレーションっていうみたい(多分)
PHPのforeachのように操作するには、for(key : array)という拡張for文を使う。

シャローコピーは参照をコピーする(ポインタをコピー)

配列の中に、オブジェクトなどの参照が格納されている場合、その参照先の実態はコピーされない。
C言語の、ポインタが格納された配列をコピーしているようなイメージ。
C言語やって、Javaやると全部ヒープ領域(多分)で変な感じがする。あるクラスに、変数に値を代入し、クラスごとに別々のオブジェクトを持ちたい場合は、ディープコピーしないといけない。
メソッドに、配列やオブジェクトを引数で渡す場合は「そのオブジェクトの参照」が渡される。
例えば、あるオブジェクトで値を受け取り、保持したい場合に・・・

public static void main(String[] args){
  ShallowBean shallowBean = new ShallowBean();
  String[] str = { "aaa", "bbb", "ccc", "ddd" };
  shallowBean.setValue(str);
}

public class ShallowBean{
  private String[] str;
  public setValue(String[] str) {
    this.str = str;
  }
}

とかやっちゃうと、shallowBeanオブジェクトへの参照がコピーされる.メイン以外の別のオブジェクトで、shallowBeanの変更があると、両方のクラスは同じshallowBeanオブジェクトを参照しているので、両方に影響がある。
いちょ、cloneもarraycopyも、配列の要素が参照型の時はシャローコピーになる。
下記は配列String[]の中身、Stringオブジェクトはコピーされないため、シャローコピーである。
clone版

public setValue(String[] str) {
  this.str = str.clone;
}

arraycopy版

public setValue(String[] str) {
  System.arraycopy(str, 0, this.str, 0, str.length);
}

String[]配列の要素、Stringオブジェクトへの参照型がコピーされる。

ディープコピーでは、参照先のオブジェクトを生成・コピー

ディープコピーしたくば、配列をイテレーションして、実態を生成・コピーすべし!