Java内部クラスの詳細


内部クラスは名前の通りです。クラスの中にはまだクラスがあります。Java内部クラスの出現はクラスの中でprvateによって修飾された変数や引用を解決しました。
メンバー内部クラス:
まず内部の書き方を見てください。
public class Outer {
	private int x=9;
	class Inner{//   
		void fun(){
			System.out.println("Inner:"+x);
		}
	}

}
は、この内部クラスとメンバー変数が同じレベルなので、メンバー内部クラスといいます。メンバー内部クラスである以上、メンバー変数の修飾子は内部クラスに完全に適用されます。内部クラスのインスタンスの作成を見てみます。
Outer.Inner inner = new Outer().new Inner();
はこのようにして内部クラスの例を得た。皆さんはこのような疑問がありますか?私の天、これは何ですか?ここでnew Outer()は外部の対象を表しています。new Inner()は内部の対象を表しています。前の定義はその種類の中の内部の種類を区別するためです。二つの内部の類名は同じです。外部の類名は違っています。
Inner inner = new Inner();
では、JVMは具体的にどのような内部を探しているのか分かりませんので、このように書くのも当然です。問題が来ました。内部のクラスで外部のメンバーにどうやってアクセスするのですか?上のコードを実行するとコンソールの出力が見えます。Inner:9です。ここではOuter.this.xを省略しています。内部クラスは外部クラスの引用を持っているので、直接に外部クラスのメンバーにアクセスすることができます。はい、上の例を簡単に修正します。
class Outer {
	private  int x=9;
	class Inner{
		int x=6;
		void fun(){
			int x=3;<span style="font-family: Arial, Helvetica, sans-serif;">//①</span>
			System.out.println("Inner:"+x);
		}
	}

}
今回の印刷結果はInner:3です。違います。上で省略したOuter.this.xは9です。これはJavaの中の近原則に関連しています。近くにこの変数があると外に持ち出しません。上の①を注釈してみたら、今回の印刷結果は6であり、依然として近くの原則です。①を注釈しないで、この3つのx変数を勝手に訪問するにはどうすればいいですか?OuterのxはOuter.this.xでInnerのxはthis.xでアクセスすればいいです。上で述べましたが、メンバー内部の修繕子は完全に内部クラスに適用されます。staticもそうです。それではstaticに修飾された内部類にはどんな特徴がありますか?静的メンバ変数と比較してもいいです。制限にアクセスしても、静的ではないものにはアクセスできません。ただし、内部クラスにアクセスする際には外部クラスのオブジェクトは必要なくなります。作成したインスタンスにもいくつかの変化があります。
new Outer.Inner();
ここでInnerクラスの実例を作成しました。
注:内部クラスの例です。外部のものではありません。コードの一部を見てください。
class Outer {
	private  int x=9;
	class Inner{
		static int x=0;//    
		void fun(){
			System.out.println(this.toString());
		}
	}
}
上記の表記の誤りの場合、JVMによるクラスローディングの順序により、必然的に優先的なローディングクラスが静的ドメインをローディングすることができ、非静的メンバーをローディングすることができる。静的なメンバはオブジェクトに依存せずにアクセスできるが、内部の変数は静的ではなく、外部のオブジェクトが必要であるため、内部の静的さは無意味になると考えられる。
内部クラス静的変数を定義する場合、内部クラス自体はstaticによって修正されなければなりません。
結節:メンバー内部クラスはメンバー変数と同じレベルで、同じレベルの才能だけがメンバー内部クラスとなり、メンバー変数の修飾子に適用されます。これは他の内部クラスにはない特性であり、内部クラスは外部クラスのメンバー変数(プライベートを含む)に任意にアクセスでき、外部クラスは内部クラスのメンバー変数にアクセスするためには外部クラスに内部クラスのオブジェクトを作成する必要があります。内部類はpublicで修飾されていることが少なく、インターフェースは除外されます。
局部内部類:局部内部類は名前の通り局部に書いています。以下は例です。
class Outer {
	public int x = 9;

	public void fun() {
		class Inner {

			void fun() {
				System.out.println(x);
			}
		}
	}
}
はここで方法に書いてあります。このクラスは非静的で、newオブジェクトがないと、fun()メソッドのクラスはロードされません。アクセス権限修飾子はメンバー変数に適用されていますので、ここでInnerの局部内部類はpublic prvate staticなどの修飾子を使用することができません。次はコードをどう見ますか?
class Outer {
	public int x = 9;

	public void fun() {
		private int x = 6;//  ,    final      
		 class Inner {

			void fun() {
				System.out.println(x);
			}
		}
	}
}
上記のコードは問題があります。誤記の注釈はすでに明記されています。その原因は局部内部の種類が方法体の中で、スタックメモリに属しています。一部の内部の種類がヒープメモリの中にあります。スタックメモリは方法の実行が終わったら直ちに空間を解放します。しかし、オブジェクトが存在し、xにアクセスすると、変数xの異常が確認されなくなります。この問題を解決するために、finalが修飾された後は定数となり、記憶空間が変更され、問題が解決されます。上のコードを引き続き修正します。
class Outer {
	public int x = 9;

	public void outerfun(final int x) {
		//  x++;
		class Inner {
			void fun() {
				System.out.println(x);
			}
		}
		new Inner().fun();
	}
}
メイン関数はこのようにアクセスします。
		outer.outerfun(1);
		outer.outerfun(2);
これでいいですか?ここの疑惑はxがfinalに飾られていますが、二回も与えられますか?答えは完全にできます。これらの2つは必然的な連絡がなくて、funメソッドを呼び出した時にスタックに押し込まれて、解放空間を実行し終わって、再度スタックに押し込まれます。だから、この2つのxは2つの異なる変数です。上のx++のコメント方法を正しく誤報します。
結節:内部類はfinalで修飾された変数にしかアクセスできません。メンバーの修飾子に修飾されてはいけません。
匿名の内部クラス:
名前の通り、名前のない部類です。内部クラスを定義するときは、クラスを引き継ぐか、インターフェースを実現する必要があります。下には匿名ではない部類の書き方があります。
abstract class AbsDemo{
	abstract void show();
}
class Outer {
	public void fun(){
		class Inner extends AbsDemo{

			@Override
			void show() {
				System.out.println("Inner:show");
			}
			
		}
	}
}
続いてInnerのオブジェクト.shou()方法で正常に呼び出すことができます。ここではshowメソッドを呼び出すためにコードを書くだけの複雑さです。次に匿名の内部クラスを使うと、内部のコードが完全に簡略化されます。
abstract class AbsDemo{
	abstract void show();
}
class Outer {
	public void fun(){
		new AbsDemo() {
			
			@Override
			void show() {
				System.out.println("Inner:show");
			}
		}.show();
	}
}
これは匿名の内部類の書き方です。抽象類は例を作ることができないことはみんな知っています。ここではnew AbsDemoの後ろに大きな括弧があります。これはAbs Demoの抽象的な方法と同じです。括弧が終わったらAbsDemoのサブクラス(親の書き方を書き換えることができる方法は必ずサブクラスです。)ができます。実のところ
匿名の内部クラスの実質は匿名のサブクラスのオブジェクトであり、匿名の内部クラスを書くということは、上書き方法のために簡略化された書き方であるが、親のような方法が5つあり、匿名の内部カバーを使うと読書性が特に悪いことが分かります。
class Outer {
	public void fun(){
		new AbsDemo() {
			
			@Override
			void show() {
				System.out.println("Inner:show");
			}
			//      
			void method(){
				System.out.println("method");
			}
		}.show();
	}
}
は、親の方法を呼び出して、その後で直接show()を使えばいいです。その子の特有の方法はどうやって呼び出されますか?考えなくてもいいです。この方法は子供特有で、子の種類は名前がないので、子の種類のインスタンスを使ってこのオブジェクトを受け入れることはできません。親の種類のコールを使うと、依然として間違いがあります。これも匿名の部類の別の弊害です。ショー()でint x=5を定義する。これもいいです。AbsDemo(){}ここはクラスの大かっこです。クラスでメンバー変数とメンバー方法を定義できます。この書き方は確かによくないです。このように簡略化のために現れた匿名内部類はその意味を失いました。
リボン:匿名内部クラスは簡略化のために生成され、クラスを作成した直後に実行されるために、Android開発ではしばしば匿名内部クラスが使用される。
出典:http://blog.csdn.net/u010829905/article/details/47667085