LoginSignup
0
2

More than 3 years have passed since last update.

【Java】「final変数」と「不変オブジェクト」の違い

Posted at

どーも、ふぎとです。
今回はfinal変数と不変オブジェクトについて
まとめてみました。

final変数

final変数とは、final修飾子を指定した変数のこと。
その性質は「変更不可・読み込み専用」と呼ばれる
が、厳密には「再代入不可の変数」。

    final int i = 3;
    i = 5; //再代入によるコンパイルエラー

上では、基本型(int型)変数iにfinalを指定している。
基本型変数は、変数の値に「値そのもの」が保持される
変数だ(詳細は『基本型変数の代入と参照型変数の代入
の違い
』を参照)。そのため、「値そのもの」を入れ替
える再代入はコンパイルエラーになる。つまり、基本型
変数に限って言えば、final変数は「変更不可」である
ように見える。
話をややこしくしているのは、final指定の参照型変数だ。

    final StringBuilder sb = new StringBuilder("123");
    sb = new StringBuilder("456"); //コンパイルエラー

    final StringBuilder sb2 = new StringBuiler("789");
    sb.append("★");         //コンパイルエラーにならない!
    System.out.println(sb2); //"789★"が出力される

上の例では、参照型変数sbとsb2に対して操作をしている。
ここで、final変数の性質を「変更不可」と理解していると、
sbへの操作がエラーになり、sb2への操作がそうならない事
の意味がわからなくなる。
ここで、参照型変数が保持している値を思い出してみると、
これは「オブジェクトへの参照」であった。つまり、sbや
sb2が持っているのは、"123"や"789"という「値そのもの」
ではない。彼ら(?)が持っているのは、あくまでも「"1
23(456)"という状態となったオブジェクトへの参照」なのだ。
この仕組みと、final変数の厳密な定義「再代入不可」とを考
えに入れると、上の例を理解することができる。すなわち、
sbに対する "sb = new StringBuilder("456")"という操作、これ
は「新たな参照の値をsbに再代入する」という操作だ。よっ
て、final変数の性質により、コンパイルエラーがでる。一方、
"sb2.append("★")" の操作、これは「"789"という状態を持つ
オブジェクトの状態を"789★"という状態に変える
」という操
作となる。要するに、sb2への「オブジェクトへの参照値」の
再代入は起こっていない。そのためエラーとならないのである。

不変オブジェクト

final変数が「再代入不可」の性質を持つ一方で、不変オブジェ
クトは「オブジェクトの状態変更」をも禁じている。つまり、
上の例でいうところの "sb.append("★")" の操作もできないのが
不変オブジェクトなのだ。

まとめ

・final変数は「再代入不可」の性質を持つ
・参照型変数をfinal指定すると、「参照先の変更」は
 できないが「最初に参照したオブジェクトの状態変
 更」はできる
・「最初に参照したオブジェクトの状態変更」もできない
 オブジェクトを「不変オブジェクト」と呼ぶ

...
では今回はこの辺で。ふぎとでした。

(P.S.)記事の内容への指摘などあれば
   遠慮なくお知らせくださいm(__)m

0
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2