2006.12.28

Javaのfinal属性

Javaのクラスにfinalがついていた場合、これ以上拡張、継承は出来ません。

public final class Sample {

となっていた場合、

public class Sample2 extends Sample {

とは出来ません。

また、メソッドにfinalがついていた場合は、
そのサブクラスでoverride出来ません。

変数にfinalがついていた場合は、
初期値から変更できません。

final String str = "abc"; ----①

str = "ABC"; ----②

このようにすると②でエラーが起こります。

①が

final String str; ----③

となっていた場合は、②ではエラーになりません。
しかし、②の後に

str = "DEF";

とするとエラーになってしまいます。
何も入っていないときは、一度だけ値を代入できます。

配列だった場合は、

public final String[] s1 = new String[]{"a","b","c"};
s1[0] = "3"; ----④
String[] s2 = new String[4];
s1 = s2; ----⑤

このようになっていた場合は、
④ではエラーにならず、⑤でエラーになります。

一見④で配列に入っている値を変更しているので、
エラーになるように見えますが、
finalによってロックされるのは参照するアドレスです。
⑤のように参照するアドレスを変更しようとすると
エラーになります。

では、なぜ④がエラーにならないかというと。
配列はオブジェクト型なので、直接値を保持しているのではなく、
アドレスを参照して値を取りにいきます。
④で変更したのは、配列が参照しているアドレスの先にある値です。
そしてfinalによってロックされるのは配列へのアドレスです。

アドレス1を配列へのアドレス、
アドレス2を値へのアドレスとします。

finalによってロックされるのは『アドレス1』です。
なので、『アドレス2』の先にある値は変更することが出来るわけです。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

photo
jnakamura