JAvaにおける内部クラスの使用


1.定義
 
内部クラスとは、1つの外部クラスの内部に1つのクラスを定義することである.内部クラスは外部クラスの1つのメンバーとして、外部クラスに依存して存在する.内部クラスは静的であり、protectedとprivateで修飾することができる(外部クラスはpublicとデフォルトのパケットアクセス権限しかない).内部クラスは主に以下の種類がある:メンバー内部クラス、局所内部クラス、静的内部クラス、匿名内部クラス.
 
2.なぜ内部クラスが必要なのか
 
一般的には、内部クラスがクラスから継承されたり、インタフェースが実装されたりします.内部クラスのコード操作によって外部クラスのオブジェクトが作成されます.したがって、内部クラスは外部クラスに入るウィンドウを提供していると考えられます.内部クラスを使用する最も魅力的な理由は、各内部クラスがインタフェースから独立して継承できるためです.外部クラスがこの実装を継承したかどうかにかかわらず、内部クラスには影響がない.内部クラスが提供する複数の具体的または抽象的なクラスを継承できる能力がなければ、いくつかの設計とプログラミングの問題は解決しにくい.この角度から見ると、内部クラスは多重継承の解決策が完全になった:インタフェースは一部の問題を解決し、内部クラスは有効に「マルチ継承」を実現した.
 
3.メンバー内部クラス
 
外部クラスのメンバーとして存在し、外部クラスのプロパティとメソッドと並んでいます:>>外部クラスが内部クラスにアクセスする場合は、内部クラスのオブジェクトを作成する必要があります.>>各内部クラスのオブジェクトは、外部クラスのオブジェクトにリンクされます(静的内部クラスでない限り、下に説明します)>>内部クラスでは、すべての外部クラスのメンバーにアクセスできます.ただし、自身は静的メンバーを定義できません.>>内部クラスでは、外部クラスと同じ名前のインスタンス変数を定義することができ、内部クラスで自分の変数にアクセスし、外部クラスと同じ名前の変数ではなく、直接使用することができます.外部クラスの同じ名前の変数にアクセスする場合、「外部クラス名.this.変数名」を使用します.>>内部クラスはコンパイル時の概念です.コンパイルに成功すると、まったく異なる2つのクラスになります.この例ではコンパイルが完了すると、Outer 3.classとOuter 3$Inner 3.classの2つのファイルが表示されます.例:
public class Outer3 {
	private static int i = 10;
	private int j = 20;
	private int k = 30;

	public static void outer_method1() {

	}

	public void outer_method2() {

	}

	class Inner3 {
		// static int inner_i;
		private int inner_j = 200;
		private int k = 300;

		public void inner_method() {
			System.out.println(inner_j);
			System.out.println(this.k);
			System.out.println(Outer3.this.k);
			System.out.println(j);
			outer_method1();
			outer_method2();
		}
	}

	public void outer_method3() {
		this.new Inner3().inner_method();
	}

	public static void outer_method4() {
		Outer3 outer = new Outer3();
		Inner3 inner = outer.new Inner3();
		inner.inner_method();
	}

	public static void main(String[] args) {
		outer_method4();
	}
}

 
 
4.ローカル内部クラス
 
メソッドで定義された内部クラスは、ローカル変数と似ています.メンバーの内部クラスと同じ特性を持つ以外は:>>ローカル内部クラスにはアクセス修飾子がありません.外部クラスの一部ではありません.>>役割ドメイン内の変数にアクセスできますが、アクセス時に暗黙的に変数をfinalとして処理します.例:
public class Outer4 {

	public void outer_method() {
		int i = 10;
		// i++;
	
		class Inner4 {
			void inner_method() {
				System.out.println(i);
			}
		}
	}
}

 
 
5.静的内部クラス
 
内部からのオブジェクトと外部クラスのオブジェクトとのつながりを必要としない場合は、内部クラスをstaticとして宣言できます.非静的内部クラスオブジェクトは、外部クラスのオブジェクトを指す参照を隠して保存します.しかし、静的内部クラスはそうではありません:>>外部クラスから直接内部クラスのオブジェクトを作成できます.>>内部クラスのオブジェクトに非静的外部クラスオブジェクトにアクセスできません.>>内部クラスは静的および非静的メンバーを定義できます.>>内部クラスは外部クラスの非静的メンバーにアクセスできません.例:
public class Outer5 {

	private static int i = 10;
	private int j = 20;
	private int k = 30;

	public static void outer_method1() {

	}

	public void outer_method2() {

	}

	static class Inner5 {
		private static int inner_i;
		private int inner_j = 200;
		private int k = 300;

		public void inner_method() {
			System.out.println(inner_j);
			System.out.println(k);
			// System.out.println(j);
			outer_method1();
			// outer_method2();
		}
	}

	public void outer_method3() {
		System.out.println(new Inner5().inner_j);
	}

	public static void outer_method4() {
		new Inner5().inner_method();
	}

	public static void main(String[] args) {
		outer_method4();
	}
}

 
6.匿名内部クラス
 
匿名の内部クラスはクラス名のない内部クラスであり、一般的に適用される条件は以下の通りである:>>クラスの一例にのみ使用される.>>クラスは定義後すぐに使用される.>>クラスは非常に小さい(4行のコード以下を推奨する)>>クラスに名前を付けると、コードがより理解しやすくなりません.匿名の内部クラスを使用する場合、覚えておくべき原則:>>匿名クラスには構造方法がありません.>>匿名クラスの内部では静的メンバー(属性、方法、クラス)を定義できません.>>匿名クラスはpublic、protected、private、static.>>インスタンスを作成するしかありません.>>newキーワードの後ろで、インタフェースまたはクラスを隠して実現します.>>その他の内部クラスの特性.例:
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class Outer6 {

	public static void main(String[] args) {
		List<String> name = Arrays.asList("James", "Kobe", "Yao");
		Collections.sort(name, new Comparator<String>() {
			public int compare(String s1, String s2) {
				return s1.compareTo(s2);
			}
		});
	}
}

 
静的方法Collections.sortは1つのlistと1つのComparatorを入力パラメータとして受信して、入力したlistの中の要素を比較して並べ替えることを実現します.私たちは直接newで1つのComparatorを実現して、実際には1つのComparatorを実現する匿名クラスを定義して、newを通じてこの匿名クラスの1つのオブジェクトを作成しました.この例でコンパイルに成功した後にOuter 6$1.classファイルが現れます.匿名クラスを表すコンパイルを通過する.
 
7.多層ネストクラス
 
多層ネストクラスでは、内部クラスがどれだけネストされているかは重要ではありません.privateの場合でも、埋め込まれた外部クラスのすべてのメンバーにアクセスできます.例:
public class Outer7 {
	private int i = 10;

	private void outer_method() {

	}

	class A {
		int j = 20;

		void a() {

		}

		class B {
			void b() {
				outer_method();
				a();
				System.out.println(i);
				System.out.println(j);
			}
		}
	}

	public static void main(String[] args) {
		new Outer7().new A().new B().b();
	}
}

 
8.内部クラスのリロード
 
クラスを作成し、外部クラスを継承して二次内部クラスを再定義した場合、内部クラスは再ロードされますか?しかし、「リロード」内部クラスは外部クラスの1つの方法のようで、あまり役に立たない.例:
public class Outer8 {
	private Inner inner;

	class Inner {
		public Inner() {
			System.out.println("Outer8.Inner()");
		}
	}

	public Outer8() {
		System.out.println("new Outer8()");
		inner = new Inner();
	}
}

 
public class SubOuter8 extends Outer8 {
	private Inner subinner;

	class Inner {
		public Inner() {
			System.out.println("SubOuter8.Inner()");
		}
	}

	public SubOuter8() {
		System.out.println("new SubOuter8()");
		subinner = new Inner();
	}

	public static void main(String[] args) {
		new SubOuter8();
	}
}

 
運転結果:new Outer 8()Outer 8.Inner()new SubOuter 8()SubOuter 8.Inner()
このように,外部クラスを継承する場合,内部クラスには特に変化はなく,この2つの内部クラスは完全に相対的に独立した2つのエンティティであり,それぞれが自分のネーミング空間内にある.もちろん,ある内部クラスを明確に継承することもできる.例:
public class Outer8 {
	private Inner inner;

	class Inner {
		public Inner() {
			System.out.println("Outer8.Inner()");
		}
	}

	public Outer8() {
		System.out.println("new Outer8()");
		inner = new Inner();
	}
}

 
public class SubOuter8 extends Outer8 {
	private Inner subinner;

	class Inner extends Outer8.Inner {
		public Inner() {
			System.out.println("SubOuter8.Inner()");
		}
	}

	public SubOuter8() {
		System.out.println("new SubOuter8()");
		subinner = new Inner();
	}

	public static void main(String[] args) {
		new SubOuter8();
	}
}

 
運転結果:new Outer 8()Outer 8.Inner()new SubOuter 8()Outer 8.Inner()SubOuter 8.Inner()
前述の結果よりも「Outer 8.Inner()」が多く出力、子クラスの内部クラスがインスタンス化時に親クラスの内部クラスのオブジェクトを先に作成したことを示す.
 
小結:異なる環境の下の内部クラスは異なる特性を持っていて、メンバーの内部クラスはクラスの他のメンバーの特性と似ています;ローカル内部クラスはローカル変数の特性と似ている.静的内部クラスは静的変数の特性と似ている.匿名の内部クラスは、ある機能のためにあるインタフェースを実現する際によく用いられる.同時に、内部クラスもクラスの表現形式である.