変換:匿名の内部クラスとローカルの内部クラスはfinal変数にしかアクセスできない理由



匿名の内部クラスがメソッドの内部に現れるため、変数の役割ドメインの問題です.このメソッドのパラメータまたはメソッドで定義された変数にアクセスする場合は、これらのパラメータと変数をfinalに修飾する必要があります.匿名の内部クラスはメソッドの内部にあるが、実際にコンパイルする場合、内部クラスはOuterにコンパイルされるからである.Inner,これは内部クラスの位置と外部クラスのメソッドが同じレベルにあることを示し,外部クラスのメソッドの変数またはパラメータはメソッドの局所変数にすぎず,これらの変数またはパラメータの役割ドメインはこのメソッドの内部でのみ有効である.コンパイル時に内部クラスとメソッドが同じレベルにあるため、メソッドの変数やパラメータはfinalであり、内部クラスのみ参照できます.
Javaコード
package com.cxz.j2se;      
  •      
  • public class MyClass {      
  •     public MyClass() {      
  •         final int finalValue = 10;      
  •         int not$Final = 20;      
  •         MyInterface myInterface = new MyInterface() {      
  •             public void functionWithoutPara() {      
  •                 //compile Error      
  •                 //System.out.println(noFinal);       
  •                 System.out.println(finalValue);      
  •             }      
  •      
  •             public void functionWithPara(int num) {      
  •                 System.out.println("The parameter " + num      
  •                         + " has been passed by the method");      
  •             }      
  •      
  •         };      
  •         myInterface.functionWithoutPara();      
  •         myInterface.functionWithPara(not$Final);      
  •         System.out.println(myInterface.getClass().getName());      
  •     }      
  •      
  •     public static void main(String[] args) {      
  •         new MyClass();      
  •      
  •     }      
  •      
  • }    
  • package com.cxz.j2se;   
      
    public class MyClass {   
        public MyClass() {   
            final int finalValue = 10;   
            int not$Final = 20;   
            MyInterface myInterface = new MyInterface() {   
                public void functionWithoutPara() {   
                    //compile Error   
                    //System.out.println(noFinal);    
                    System.out.println(finalValue);   
                }   
      
                public void functionWithPara(int num) {   
                    System.out.println("The parameter " + num   
                            + " has been passed by the method");   
                }   
      
            };   
            myInterface.functionWithoutPara();   
            myInterface.functionWithPara(not$Final);   
            System.out.println(myInterface.getClass().getName());   
        }   
      
        public static void main(String[] args) {   
            new MyClass();   
      
        }   
      
    }  

    二、なぜ局所内部クラスがfinal変数にしかアクセスできないのかは簡単に言えば役割ドメインの問題である.メソッドの外でやっていることは、メソッド内で定義された変数を変えることはできません.メソッドの中にこの時点でこの局所変数が存在しているかどうか分からないからです.この内部クラスではメソッドのローカル変数は失効します.つまり、役割ドメイン内ではないのでアクセスできませんが、なぜfinalでアクセスできるのでしょうか.Javaはcopy local variable方式で実現されているため、finalと定義された局所変数をコピーして使用し、参照したものも持ってきて使用することができますが、再割り当てはできません.これによりaccess local variableのダミーが作成されますが、この場合は再割り当てができないため、一般的に予想できないことは起こりません.3、ローカル内部クラスを定義し、ローカル内部クラスが外部で定義されたペアを使用している場合、なぜコンパイラはパラメータ参照がfinalであることを要求しますか.注:匿名の内部クラスを含むローカル内部クラス.理由は次のとおりです.
    Javaコード
    abstract class ABSClass{   
  • public abstract void print();   
  • }   
  •   
  • public class Test2{   
  • public static void test(final String s){//パラメータが匿名クラス内で使用されると、final
  • でなければなりません.
  • ABSClass c=new ABSClass(){   
  • public void print(){   
  • System.out.println(s);   
  • }   
  • };   
  • c.print();   
  • }   
  • public static void main(String[] args){   
  • test("Hello World!");   
  • }   
  • }  
  • abstract class ABSClass{
    public abstract void print();
    }
    
    public class Test2{
    public static void test(final String s){//            ,    final
    ABSClass c=new ABSClass(){
    public void print(){
    System.out.println(s);
    }
    };
    c.print();
    }
    public static void main(String[] args){
    test("Hello World!");
    }
    }

    JVMの各プロセスには複数のルートがあり、各static変数、メソッドパラメータ、ローカル変数はもちろん参照タイプを指す.ベースタイプはルートとすることができず、ルートは実は記憶アドレスである.ごみ回収器は、作業中にルートから参照されたオブジェクトを巡り、タグ付けします.これにより、最後尾に戻り、すべてのルートが遍歴した後、タグ付けされていないオブジェクトの説明が参照されません.すなわち、回収可能なオブジェクト(一部のオブジェクトにはfinalizedメソッドがある、参照されていないが、JVMにはfinalizedメソッドが実行されるまでそのキューから本当に参照されていないオブジェクトとして除去する専用のキューがある、回収可能である、これは本主題の議論に関係なく、世代の区分などを含めて後で説明する).これはよく見えます.しかし、内部クラスのコールバックメソッドでは、sは静的変数でもメソッドの一時変数でもメソッドパラメータでもなく、ルートとして使用することはできません.内部クラスでも変数として参照することはできません.そのルートは内部クラスの外部のメソッドで、外部変数sが他のオブジェクトを再指向すると、コールバックメソッドのこのオブジェクトsは参照を失います.回収される可能性があるが、内部クラスのコールバック方法の多くは他のスレッドで実行されるため、回収後もアクセスを継続する可能性がある.これはどんな結果になりますか?final修飾子を使用すると、オブジェクトの参照が変更されないだけでなく、コンパイラはコールバックメソッドでのオブジェクトのライフサイクルを維持し続ける.これがfinal変数とfinalパラメータの根本的な意味です文章出典:飛諾網(www.firnow.com):http://dev.firnow.com/course/3_program/java/javajs/20100719/460085.html