今日は Java の内部クラスについて復習します。内部クラスには一般的に以下の種類があります:静的内部クラス、メンバー内部クラス、匿名内部クラス、メソッド内部クラス。以下では、主に静的内部クラスとメンバー内部クラスについて紹介します。主な内容は以下の通りです:
- 概要
- 静的内部クラス
- メンバー内部クラス
- 匿名内部クラスとメソッド内部クラス
- まとめ
概要#
名前が示すように、内部クラスはクラスの内部に定義されたクラスです。内部クラスは独立したクラスであり、コンパイル後には独立した .class ファイルが生成され、その名前の前には外部クラスのクラス名と $ 記号が付きます。内部クラスも private、default、protected、public 修飾子を使用できます。以下は内部クラスの書き方の具体例です:
/**
* 内部クラス
* @author jzman
*/
public class OutterClass {
//静的内部クラス
private static class StaticInnerClass{
}
//メンバー内部クラス
private class FieldInnerClass{
}
//匿名内部クラス
Runnable runnable = new Runnable() {
@Override
public void run() {
}
};
private void method() {
//メソッド内部クラス(局所内部クラス)
class InnerClass{
}
}
}
静的内部クラス#
- 静的内部クラスは静的メンバーと非静的メンバーを持つことができます。
- 静的内部クラスは外部クラスの静的メンバーと静的メソッドを直接呼び出すことができますが、外部クラスの非静的メンバーと非静的メソッドを呼び出すことはできません。
- 無関係なクラスの中で、静的内部クラスのオブジェクトを直接作成できます。
- 静的内部クラスは外部クラスとの関係が少なく、その作成は基本的に外部クラスに依存しません。
/**
* 静的内部クラス
* @author jzman
*/
public class StaticInnerClassDemo {
public static void main(String[] args) {
//他のクラスは非私有内部クラスのインスタンスを直接作成できます
OutterClass1.InnerClass innerClassB = new OutterClass1.InnerClass();
InnerClass innerClassA = new InnerClass();
innerClassA.testStaticInnerClass();
//...
}
}
//外部クラス
class OutterClass1{
//非静的メンバー変数
int ageA = 18;
//非静的メソッド
public void methodA() {
}
//静的メンバー変数
static int ageB = 18;
//静的メソッド
public static void methodB() {
}
private void methodC() {
//外部クラスが静的内部クラスのメソッドを呼び出す
InnerClass innerClass = new InnerClass();
innerClass.testStaticInnerClass();
}
//静的内部クラス
static class InnerClass{
public void testStaticInnerClass(){
//静的内部クラスは外部クラスの非静的メンバー変数とメソッドにアクセスできません
// System.out.println(ageA);
// methodA();
//静的内部クラスは外部クラスの静的メンバーとメソッドにアクセスできます
System.out.println(ageB);
methodB();
}
}
}
メンバー内部クラス#
- メンバー内部クラスは外部クラスのすべてのメンバーにアクセスできます。
- メンバー内部クラスのオブジェクトの作成は外部クラスのオブジェクトに依存し、外部クラスが先に存在しなければ内部クラスは存在しません。
- メンバー内部クラスは外部クラスのメンバー変数の一つです。
- メンバー内部クラスは静的メンバーを持つことはできませんが、定数は存在を許可されます。
/**
* メンバー内部クラス
* @author jzman
*/
public class FieldInnerClassDemo {
public static void main(String[] args) {
//メンバー内部クラスは外部クラスに依存し、外部クラスを越えて直接内部クラスのインスタンスを作成することはできません
// InnerClass innerClass = new InnerClass();
//他のクラスで内部クラスのインスタンスを作成する正しい方法
OutterClass2 outterClass2 = new OutterClass2();
OutterClass2.InnerClass innerClass = outterClass2.new InnerClass();
innerClass.testFieldInnerClassMethod();
}
}
//外部クラス
class OutterClass2{
//非静的メンバー変数
int ageA = 18;
//非静的メソッド
public void methodA() {
}
//静的メンバー変数
static int ageB = 18;
//静的メソッド
public static void methodB() {
}
private void methodC() {
//外部クラスがメンバー内部クラスのメソッドを呼び出す
InnerClass innerClass = new InnerClass();
innerClass.testFieldInnerClassMethod();
}
//メンバー内部クラス
class InnerClass{
//メンバー内部クラスは静的メンバーを持つことはできません
// static int a = 10;
//メンバー内部クラスは定数形式の存在を許可されます
static final int b = 10;
public void testFieldInnerClassMethod(){
//メンバー内部クラスは外部クラスのすべてのメンバー変数およびメソッド(静的および非静的)に直接アクセスできます
System.out.println(ageA);
methodA();
System.out.println(ageB);
methodB();
}
}
}
匿名内部クラスとメソッド内部クラス#
匿名内部クラスはもちろん、確定した名前を持たず、その実装はクラス本体の中で具体的に行われ、最終的に関連クラスの匿名オブジェクトが返されます。最終的に返されるのは匿名のインスタンスであるため、匿名内部クラスの後にはセミコロンを追加する必要があります。メソッド内部クラスは局所内部クラスであり、一般的にはクラスの局所位置に定義され、現在のコードブロックおよび外部クラスのすべての変数にアクセスできます。
まとめ#
クラス間のメンバー変数の相互呼び出しは、実際にはオブジェクトのメンバー変数にアクセスすることです。メンバー内部クラスが外部クラスのメンバー変数やメソッドにアクセスできるのは、内部クラスが外部クラスの参照を保持しているためです。一般的には OutterClass.this を通じて外部クラスのオブジェクトを取得します。外部クラスが内部クラスのメンバー変数やメソッドにアクセスしたい場合も、内部クラスの参照を保持する必要があります。したがって、外部クラスが内部クラスのメンバー変数やメソッドにアクセスする際には、まず内部クラスのオブジェクトを作成し、そのオブジェクトを通じて対応するメンバー変数やメソッドにアクセスする必要があります。