内部クラスのフィールドの可視性
Javaの内部クラスのフィールドはprivateにしてもエンクロージングクラスからは可視になっている。class InnerClass { private static class StaticClass { private int var = 5; } public static void main(String ... args) { class LocalClass { private int var = 3; } LocalClass local = new LocalClass(); int var = local.var; System.out.println(var); StaticClass slocal = new StaticClass(); var = slocal.var; System.out.println(var); } }実行結果
3 5
一見、privateの意義に反しているように見えるけど、あえて意図的にこのような言語設計になっているように思う。
Javaのスコープは
- 全体
- 派生クラス
- パッケージ内
- クラス内部
ブリッジメソッド
本来アクセスできないprivateフィールドにアクセスするためにJavaのコンパイラはエンクロージングクラスとprivateフィールドを結ぶブリッジメソッドを生成している。javapでブリッジメソッドが生成されている様子を見てみよう。
$ javap -l InnerClass\$1LocalClass Compiled from "InnerClass.java" class InnerClass$1LocalClass { InnerClass$1LocalClass(); LineNumberTable: line 9: 0 line 10: 4 static int access$000(InnerClass$1LocalClass); LineNumberTable: line 9: 0 }
イメージ的にはこんな感じのメソッドが自動生成されて、このアクセスメソッドを通してprivateフィールドにアクセスしている。
class LocalClass { private int var = 3; // これが自動生成される。 static int access000(LocalClass obj) { return obj.var; } }
getのみしている場合、get/setしている場合で必要なアクセサのみが作られる。
内部クラスはエンクロージングクラスの一部
privateにしてもエンクロージングクラスから可視になっている理由として、内部クラスはエンクロージングクラスの所有であり、密接な関係があると考えれば、それほどおかしくはない。そう考えると、(無名でない)内部クラスを使う場面としては以下のようなことを想定しているのかな。
- クラス外で本来の用途以外で使われないことを保証したい。
- 同じような構造が繰り返し現れる。
- メソッドは持たせない。
- 簡潔な記法にして、フィールドにアクセス修飾子をつけない。
0 件のコメント:
コメントを投稿