なぜ静的でないと内部に静的なメンバーがいないのかを探究します。

2588 ワード

まず、静的ではない内部の概念を明らかにします。
        静的でない内部クラスは以下の通りです。

public class Outer {
	class Inner {
		//public static int si = 1;  ,            
		public static final int i = 1;
	}
	public static void main(String[] args) {
		Outer outer = new Outer();
        //                       
		//Outer.Inner inner = new Outer.Inner(); 
		Outer.Inner inner = outer.new Inner();//  
System.out.println(Outer.Inner.i);//  
	}
}
        非静的な内部クラスの作成、アクセスは、外部クラスのインスタンスを通じて内部クラスにアクセスするために必要です。ベースの観点から、外部クラスのインスタンスは、内部クラスに向けたポインタを持ち、外部クラスのインスタンスを通してのみ内部クラスのデータにアクセスすることができる。
では、なぜ静的でないと内部には静的なメンバーがいないのですか?
        まずメモリ割り当ての観点から、静的メンバはクラスローディング時にメモリ空間を割り当てることがよく知られている。しかし、内部クラスについては、そのメンバーにアクセスするためには、外部クラスのインスタンスが必要であるが、クラスをロードする際には、外部クラスを内部クラスに実装することは不可能であり、したがって、外部クラスのインスタンスは、この静的なメンバーのポインタを持っていないため、内部クラスの静的なメンバーはアクセスできないので、Javaは、非静的な内部クラスの静的なメンバーを許可しない。
        なぜOuter.Inner.siで訪問できないのかという質問があります。このようにして、静的な内部クラスの静的なメンバーとのアクセスが繰り返されると、Javaの定義に違反する非静的な内部クラスは、外部クラスのインスタンスに依存するという原則がある。
        一つの場合は

public static final int i = 1;
         どうしてfinalを追加すればいいですか?Outer.Inner.iを通じてアクセスするのは規則違反ですか?ここでOuter.Inner.iは変数によって訪問されていません。コンパイラでstaticに対して値が確定されました。  final宣言の変数を最適化します。定数でstaticを交換します。  final宣言の変数ですので、ここではOuter.Inner.iの代わりに定数1を使用します。finalはstaticブロック内で値を初期化することができますが、静的でない内部クラスは、コンパイラの最適化の必要性と非静的内部クラスが外部クラスのインスタンスの特殊性に依存するため、非静的な内部クラスのstaticを許可しませんでした。  finalは基本タイプ(int,shot,long byte,double,float,char,bootlean)と文字列(String)タイプのみに使用できます。
         Outer.Inner.iが差し替えられている具体的な証拠は、classバイトコードを見てください。
22、25、26行分

 //   :4,  :3
 public static void main(java.lang.String[] args);
     0  new Outer [1]
     3  dup
     4  invokespecial Outer() [16]
     7  astore_1 [outer]
     8  new Outer$Inner [17]
    11  dup
    12  aload_1 [outer]
    13  dup
    14  invokevirtual java.lang.Object.getClass() : java.lang.Class [19]
    17  pop
    //      ,Inner         Outer   ,
    //      Outer       
    18  invokespecial Outer$Inner(Outer) [23] 
    21  astore_2 [inner]
    //     (   )
    22 getstatic java.lang.System.out :java.io.PrintStream [26] 
    25  iconst_1//            ,        1     
    //      int     ,  println  
    26  invokevirtual java.io.PrintStream.println(int) : void [32]
    29  return
        なぜ静的でないと内部クラスに静的なメンバーがいないのかという問題については、ここまで探究しました。