内部クラス(インナークラス)
- エンクロージングインスタンスのprivateフィールドにアクセス可能
- ネストしたクラスにはインナークラス、staticインナークラス、ローカルクラス、匿名クラスがある。
- ローカルクラスは、メソッド内で定義されるクラスのことで、abstract, finalで修飾できる。
- 匿名クラスはあらゆる修飾子を使用することはできない。
- インナークラスのインスタンスを生成するには、エンクロージングクラスのインスタンスを先に生成する必要がある。
new Outer().new Inner()
- staticインナークラスはエンクロージングクラスのインスタンス化は不要。
new Inner(), new Comparator()など
- ローカルクラスから参照するローカル変数は、ローカルクラスよりもあとにローカル変数を宣言すると
コンパイルエラー
。また、その時のローカル変数は実質的にfanalでなければならない。(値を変更しようとするとコンパイルエラー
) - 匿名クラスには名前がないため、コンストラクタは定義できない(
コンパイルエラー
) - 匿名クラスを 初期化したいときは初期化子{}を使う
- クラスやインターフェースで定義したstaticメソッドはオーバライドできない。@Overrideアノテーションを付けたりすると
コンパイルエラー
- スーパークラスとインターフェースが同一のシグニチャのメソッドを持っている場合、スーパークラスのメソッドが優先される。
内部クラスのインスタンス化
Inner inner = new Outer().new Inner();
静的クラス(staticクラスの内部クラス)
- エンクロージングクラスのprivate staticなフィールドにアクセス
- エンクロージングクラスの非staticなフィールドやメソッドにはアクセスができない
静的クラスのインスタンス化
InnerStatic inner = new Outer.InnerStatic();
無名(匿名)クラス
- 名前を持たないクラス通常のクラスと異なり定義と同時にインスタンス化される
- 実装するクラスやインターフェースをnewするコード実装を記述する
- 明示的なコンストラクタは持たない(定義できない)
- コンストラクタの代わりに初期化子「{}」を使用することができる。
- extends節やimplements節はつかえない
- メソッドのオーバーライドはOK
public class OuterAnonymous {
public void printMessage(int type, String content) {
new Object() {
PrintStream getOutput() {
return type == 0 ? System.out : System.err;
}
}.getOutput().print(content);
}
}