Java – ミュータブル/イミュータブル

概要

“immutable”の説明として、「オブジェクト生成後にその内容を変えることができないオブジェクトを”イミュータブルである”」というらしい。いま一つわかり辛かったので、以下の様に考えてみた。

オブジェクトへの参照値が変わらないのにその内容が変わり得るのがミュータブル、オブジェクトの参照値が変わらなければその内容が変わり得ないのがイミュータブル、というのはどうだろうかと考えた。

これをJavaのint型、配列、String型で確認してみる。

プリミティブ型はイミュータブル

以下のコードで考える。

  • i2i1をそのまま代入しているだけなので、==比較はtrue
    • そのi2インクリメントしてもi1は影響を受けず、i1i2==比較はfalseになる
  • i3i1と同じ値をリテラルで設定していて、i1との==比較はtrue
  • i4i1と異なる値を代入していて、i1との==比較はfalse
  • i5i4と同じ値を計算した上で代入しており、i4 == i5

int型などのプリミティブ型は、変数ごとにスタック上に内容が保存されるため、オブジェクトのような参照をしない。その挙動から「プリミティブ型はイミュータブルである」ともいえる。

これをラッパークラスのIntegerで試しても同じ結果になる。

配列はミュータブル

配列はミュータブルなオブジェクトで、参照している内容を直接変更することができる。

以下の様に、2つの変数が同じインスタンスを参照している場合、一方でその内容を変更すると他方でもそれが反映される。

ただし同じ内容でもリテラルで初期化した場合は別のインスタンスとして保持され、一方への変更が他方へは影響しない。

Stringはイミュータブル

String型はイミュータブルなオブジェクトで、詳細はこちらにまとめた

String型の文字列インスタンスはヒープ上に保存され参照される。リテラルの内容が同じ場合は1つのインスタンスを共有してこれを参照する。

参照されている実体の内容が直接操作され変更されることはなく、変数同士で参照値を代入した場合に一方への変更が他方に影響することはない。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です