浅いコピーと深いコピー

コピーには浅いコピーと深いコピーがあり、変数の型によって異なるため注意が必要です。

Javaの場合、どのように気をつけるといいかを書きます。

浅いコピー

実体(インスタンス)への参照をコピーします。

実体Aへの参照aをコピーして参照bを作ったとすると、

参照bで実体Aを操作すれば、参照aで実体Aを参照したとき、その影響を受けます。

主に参照型の変数(Javaなら型名の頭文字が大文字のものや、リストなど)で代入やcloneメソッドを使うとこの現象がおきます。

それを回避するには、

String text1 = "aaa";
String text2 = text1;     //参照のコピー
text2 = new String(text2);    //新しいインスタンスを生成

のように新しくインスタンスを作り直すことが必要です。

深いコピー

実体(インスタンス)そのものを複製します。

そのため、複製した実体を変更しても、複製元の実体には影響が及びません。

普通に代入、cloneしても深いコピーになるのはプリミティブ型の変数です。

具体的には、

  • byte
  • short
  • int
  • long
  • char
  • float
  • double
  • boolean

の8つです。


言語によって少し仕様が異なるようです。

例えばPythonでは、引数には全て参照が渡されます。

しかし、参照が渡されたあと、その関数内で値が変更されたとき、渡した値自体が変更されるかはオブジェクトのタイプによります。

  • Immutable :int,float,str等
  • Mutable :list,dict等

Immutableはコピー先で値を変更してもコピー元に影響は及ばないのですが、

Mutableではコピー先で値を変更するとコピー元にも変更が反映されます。

これを回避するためには、copyモジュールのdeepcopy()関数を用いればオーケーです。

コードを書く時には常に意識しないと思わぬエラーにぶつかってしまいます。