Java内部クラス完全解説: ネストクラス・匿名クラス・静的ネストクラスの設計と活用
この章ではJavaの内部クラス(インナークラス)について説明します。
ネストクラス
Javaでは、メソッドと同様に、クラスの変数も別のクラスをメンバとして持つことができます。クラスの中にクラスを書くことはJavaで許可されています。内側に書かれたクラスをネストクラス(入れ子クラス)と呼び、内部クラスを保持するクラスをアウタークラス(外部クラス)と呼びます。
構文
ネストクラスを書く構文は以下の通りです。ここではOuter_Demoがアウタークラス、Inner_Demoがネストクラスです。
class Outer_Demo {
class Inner_Demo {
}
}
ネストクラスは2つのタイプに分類されます。
- 非静的ネストクラス - クラスの非静的メンバ
- 静的ネストクラス - クラスの静的メンバ
内部クラス(非静的ネストクラス)
内部クラスはJavaのセキュリティメカニズムの一つです。クラスをprivateアクセス修飾子で修飾することはできませんが、クラスを他のクラスのメンバとして持つ場合、内部クラスをprivateにできます。また、クラスのprivateメンバにアクセスするためにも使用されます。
内部クラスは定義の仕方と場所によって3つのタイプに分類されます。
- 内部クラス(メンバクラス)
- メソッドローカル内部クラス
- 匿名内部クラス
内部クラス(メンバクラス)
内部クラスの作成は非常にシンプルです。クラスの中にクラスを書くだけです。通常のクラスとは異なり、内部クラスはprivateにでき、一度privateと宣言すると、クラス外部のオブジェクトからアクセスできなくなります。
内部クラスを作成し、アクセスするプログラムです。この例では内部クラスをprivateにし、メソッドを通じてクラスにアクセスします。
例
class Outer_Demo {
int num;
// 内部クラス
private class Inner_Demo {
public void print() {
System.out.println("This is an inner class");
}
}
// 内部クラスへのアクセス
void display_Inner() {
Inner_Demo inner = new Inner_Demo();
inner.print();
}
}
public class My_class {
public static void main(String args[]) {
// アウタークラスをインスタンス化
Outer_Demo outer = new Outer_Demo();
// display_Inner()メソッドを呼び出し
outer.display_Inner();
}
}
Outer_Demoがアウタークラス、Inner_Demoが内部クラス、display_Inner()は内部クラスをインスタンス化するメソッドで、このメソッドはmainメソッドから呼び出されます。
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
This is an inner class.
privateメンバへのアクセス
前述の通り、内部クラスはクラスのprivateメンバにアクセスするためにも使用されます。privateメンバを持つクラスがある場合、その中に内部クラスを書き、内部クラス内のメソッド(例:getValue())からprivateメンバを返し、最終的に(privateメンバにアクセスしたい別のクラスから)内部クラスのgetValue()メソッドを呼び出します。
内部クラスをインスタンス化するには、最初にアウタークラスをインスタンス化する必要があります。その後、アウタークラスのオブジェクトを使用して、以下のように内部クラスをインスタンス化します。
Outer_Demo outer = new Outer_Demo();
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
以下のプログラムは内部クラスを使用してクラスのprivateメンバにアクセスする方法を示します。
例
class Outer_Demo {
// アウタークラスのprivate変数
private int num = 175;
// 内部クラス
public class Inner_Demo {
public int getNum() {
System.out.println("This is the getnum method of the inner class");
return num;
}
}
}
public class My_class2 {
public static void main(String args[]) {
// アウタークラスをインスタンス化
Outer_Demo outer = new Outer_Demo();
// 内部クラスをインスタンス化
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
System.out.println(inner.getNum());
}
}
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
This is the getnum method of the inner class: 175
メソッドローカル内部クラス
Javaではメソッド内にクラスを書くことができ、これはローカルタイプとなります。ローカル変数と同様に、内部クラスのスコープはメソッド内に制限されます。
メソッドローカル内部クラスは、内部クラスが定義されているメソッド内でのみインスタンス化できます。以下のプログラムはメソッドローカル内部クラスの使用方法を示します。
例
public class Outerclass {
// アウタークラスのインスタンスメソッド
void my_Method() {
int num = 23;
// メソッドローカル内部クラス
class MethodInner_Demo {
public void print() {
System.out.println("This is method inner class " + num);
}
}
// 内部クラスの終了
// 内部クラスへのアクセス
MethodInner_Demo inner = new MethodInner_Demo();
inner.print();
}
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.my_Method();
}
}
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
This is method inner class 23
匿名内部クラス
クラス名なしで宣言された内部クラスを匿名内部クラスと呼びます。匿名内部クラスの場合、宣言とインスタンス化を同時に行います。一般的に、クラスまたはインターフェースのメソッドをオーバーライドする必要があるときに使用されます。匿名内部クラスの構文は以下の通りです。
構文
AnonymousInner an_inner = new AnonymousInner() {
public void my_method() {
........
........
}
};
以下のプログラムは匿名内部クラスを使用してクラスのメソッドをオーバーライドする方法を示します。
例
abstract class AnonymousInner {
public abstract void mymethod();
}
public class Outer_class {
public static void main(String args[]) {
AnonymousInner inner = new AnonymousInner() {
public void mymethod() {
System.out.println("This is an example of anonymous inner class");
}
};
inner.mymethod();
}
}
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
This is an example of anonymous inner class
同様に、具象クラスのメソッドやインターフェースのメソッドも匿名内部クラスでオーバーライドできます。
引数としての匿名内部クラス
一般的に、メソッドがインターフェース、抽象クラス、具象クラスのオブジェクトを受け取る場合、インターフェースを実装し、抽象クラスを継承し、そのオブジェクトをメソッドに渡します。クラスの場合は直接渡せます。
しかし、上記3つのすべてのケースで、匿名内部クラスをメソッドに渡すことができます。メソッド引数として匿名内部クラスを渡す構文は以下の通りです。
obj.my_Method(new My_Class() {
public void Do() {
.....
.....
}
});
以下のプログラムは匿名内部クラスをメソッド引数として渡す方法を示します。
例
// インターフェース
interface Message {
String greet();
}
public class My_class {
// Messageインターフェースのオブジェクトを受け取るメソッド
public void displayMessage(Message m) {
System.out.println(m.greet() + ", This is an example of anonymous inner class as an argument");
}
public static void main(String args[]) {
// クラスをインスタンス化
My_class obj = new My_class();
// 匿名内部クラスを引数として渡す
obj.displayMessage(new Message() {
public String greet() {
return "Hello";
}
});
}
}
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
Hello, This is an example of anonymous inner class as an argument
静的ネストクラス
静的内部クラスとは、アウタークラスの静的メンバであるネストクラスのことです。他の静的メンバを使用して、アウタークラスをインスタンス化せずにアクセスできます。静的メンバと同様に、静的ネストクラスはアウタークラスのインスタンス変数とメソッドにアクセスできません。静的ネストクラスの構文は以下の通りです。
構文
class MyOuter {
static class Nested_Demo {
}
}
静的ネストクラスのインスタンス化は内部クラスとは少し異なります。以下のプログラムは静的ネストクラスの使用方法を示します。
例
public class Outer {
static class Nested_Demo {
public void my_method() {
System.out.println("This is my nested class");
}
}
public static void main(String args[]) {
Outer.Nested_Demo nested = new Outer.Nested_Demo();
nested.my_method();
}
}
上記プログラムをコンパイル・実行すると以下の結果になります。
出力
This is my nested class
Java
- Javaのfinalキーワード完全解説:変数、メソッド、クラスでの活用法
- Java instanceof演算子完全ガイド:基本から継承・インターフェースまで
- Javaネストクラスとインナークラス完全ガイド:種類、例、ベストプラクティス
- Java Staticネストクラスの理解:用法、違い、実例
- Java無名インナークラス完全ガイド:定義、構文、実践例
- Javaシングルトンパターン完全解説:安全な実装と活用法
- Javaリフレクション完全ガイド:実行時のクラス・メソッド・フィールド検査
- Java ObjectOutputStream完全ガイド:シリアル化、メソッド、実践例
- Javaジェネリクス完全ガイド:再利用可能で型安全なコードの構築
- Javaファイル操作のマスター:java.ioによる作成・読み取り・書き込み・削除
- Javaオブジェクトとクラス:コアOOP概念を完全理解