JAVA内部類のまとめ

6020 ワード

前言
仕事の経験の増加に従って、ますます基础の重要性を感じて、だから最近通勤する地下鉄の上ですべていくつか基础のものを见て、先日心を拭いて兄の言う内部类を见て、自分の概念に対する理解が间违っているため、いくつか困惑をもたらして、自分で昼ごろやっと分かった(ちょうど朝退屈な周例会を开いて、私はそこで自分で资料を调べて、また大学の学友を引き延ばして一绪に讨论します)、だから时间を割いてこの部分を更に整理して、分かち合って、自分のこの部分に対する理解を深めることができます.
本文
1つのクラスまたはメソッドに定義されたクラスを内部クラスと呼びます.
内部クラスには、次の4つのクラスがあります.
  • メンバー内部クラス
  • ローカル内部クラス
  • 静的内部クラス
  • 匿名内部クラス
  • 一つ一つ分解してみましょう
  • メンバー内部クラス最も一般的な内部クラス.メンバー変数のようにクラスの内部に定義されます.コード形式は次のとおりです.
  • public class OuterClass {
    
        class InnerClass {
            private void method() {
                System.out.println("innerMethod");
            }
        }
    }
    

    呼び出し方法:
        OuterClass out = new OuterClass();
        OuterClass.InnerClass in = out.new InnerClass();
        in.method();
    

    注:直接new outClass.InnerClass()メンバー内部クラスではなく、privateタイプとstaticタイプのメンバーを含む外部クラスのメンバー属性とメンバーメソッドに無条件にアクセスできます.これは、メンバー内部クラスに外部クラスの参照が暗黙的に保持されているためです.
    使用シーン:クラスAがクラスBを使用する必要があり、同時にBがAのメンバー/メソッドにアクセスする必要がある場合、BをAのメンバー内部クラスとすることができます.private内部クラスを使用して、他のクラスがその内部クラスにアクセスすることを禁止し、具体的な実装の詳細を完全に隠すことができます.
  • ローカル内部クラスコードブロックまたはメソッドで作成されたクラス.ローカル内部クラスの役割ドメインは、その存在するコードブロックまたはメソッド内でのみ作成でき、他の場所ではそのクラスのオブジェクトを作成できない.ローカル内部クラスは、役割ドメインの小さいメンバー内部クラスとして理解できる.コード形式は以下の通りである:
  •     public void test() {
            class PartInnerClass {
                private void method() {
                    System.out.println("partInnerMethod");
                }
            }
            new PartInnerClass().method();
        }
    

    シーンの使用:ローカル内部クラスは、現在のメソッドまたはコードブロックで作成、使用する場合にのみ使用され、使い捨て製品に属し、シーンの使用は少ない.
  • 静的内部クラスstaticキーワードで修飾された内部クラスは静的内部クラスであり、静的内部クラスは外部クラスの参照を持たず、外部クラスと平レベルのクラスと見なすことができる.コード形式は以下の通りである:
  • public class OuterClass {
    
        static class StaticInnerClass {
            private void method() {
                System.out.println("staticInnerMethod");
            }
        }
    }
    

    静的内部クラスで外部クラスにアクセスするメンバーはnewの外部クラスのオブジェクトしかアクセスできません.そうしないと、外部クラスの静的プロパティと静的メソッドしかアクセスできません.
    使用シーン:1.クラスAがクラスBを使用する必要があり、Bが外部クラスAのメンバー変数やメソッドに直接アクセスする必要がない場合、BをAの静的内部クラスとして使用できます.
    2.一例の実現:
    public class Singleton {
    
        private Singleton() {}
    
        private static class InnerClass {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance() {
            return InnerClass.INSTANCE;
        }
    }
    

    InnerClassは内部クラスであり、外部クラスSingletonのgetInstance()でのみ使用されるため、ロードされるタイミングはgetInstance()メソッドが初めて呼び出されたときである.初期化時にClassLoaderによって同期が保証され、INSTANCE変量が一度しか初期化できないことを確保し、INSTANCEを真・単例とする.
  • 匿名内部クラス匿名内部クラスは、以前は理解が不十分だったために困惑していたことに重点を置く必要がある.匿名内部クラスの特徴を要約すると、1.親クラスを継承したり、インタフェースを実装したりしなければならない.追加の方法を追加する必要はなく、継承方法の実装や上書きだけである.2.オブジェクトインスタンスを取得するためには、オブジェクトインスタンスを取得する必要はなく、実際のタイプを知る必要があります.3.匿名内部クラスの匿名とは、参照なしではなくクラス名を指します.4.匿名内部クラスには構築方法がなく、初期化コードブロックしかありません.コンパイラは構築方法を生成して呼び出すのに役立ちます.5.匿名内部クラスで使用されるパラメータはfinalとして宣言する必要があります.そうしないと、コンパイラはエラーを報告します私が以前理解していた偏差は第3条で、いいでしょう、実は第3条は私が自分で補充したので、みんなが私と同じ間違いを避けるために(前に何人かの同級生と討論した時、みんなはこの点に対する理解があいまいでした).コード形式は以下の通りです:
  •     button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
            }
        });
    

    私たちがよく使うボタンをクリックして傍受するのは匿名の内部クラスです.上の例はよく理解されています.次の例を見てみましょう.
        @SuppressLint("HandlerLeak")
        Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                ...
            }
        };
    

    そうですね.このnewから出てきたHandlerも匿名の内部クラスです.私はこれを見たとき、呆然としていました.どの内部クラスなのか判断できませんでした.だから、匿名の内部クラスの匿名とは、引用していないのではなく、クラス名がないことを指しています.そのタイプはHandlerだと言わないでください.Handlerのサブクラスにすぎません.クラス名がありません.のサブクラスです.ちなみに、このような書き方はメモリの漏洩を引き起こす可能性があります.この匿名の内部クラスは外部クラスの参照を暗黙的に保持するためです.例を挙げます.
        Message message = Message.obtain();
        message.what = 233;
        mHandler.sendMessageDelayed(message, 1000 * 60 * 10);
        finish();
    

    メッセージを処理するために10分遅れたMessageを送信しました.Messageが送信される前に、現在のActivityを終了しました.Messageはメッセージ・キューで10分遅れて処理されました.MessageはHandlerを参照し、HandlerはActivityの参照を暗黙的に保持し、GCが発生したときにMessage–Handler–Activityの参照チェーンによってActivityの参照が発生しました回収できないため、メモリの漏洩が発生しました.解決策は、弱いリファレンスWeakReferenceを使用するか、Handlerを静的内部クラスに設計することです.
    では、なぜ匿名内部クラスでパラメータをfinalと宣言する必要があるのでしょうか.匿名内部クラスはオブジェクトを作成して返すため、このオブジェクトのメソッドが呼び出されるタイミングが不確定で、メソッドにはパラメータを変更する可能性があります.匿名内部クラスでパラメータを変更した場合、外部クラスのパラメータは同期して変更する必要がありますか?Javaはこのような問題を回避するために、制限します匿名の内部クラスがアクセスする変数はfinal修飾を使用する必要があります.これにより、アクセスする変数が可変でないことを保証できます.
    シーンの使用:インタフェースを実装する必要がありますが、リファレンスを保持する必要はありません.
    補足
    静的内部クラスを除いて、残りのメンバー内部クラス、ローカル内部クラス、匿名内部クラスは、外部クラスの参照をデフォルトで暗黙的に保持します.
    もう2つの典型的なテーマを融通してください.
    ?に適切なコードを記入し、プログラムをコンソールに30,20,10出力させる.
    public class OuterClass {
    
        private int num = 10;
    
        class InnerClass {
            int num = 20;
    
            void show() {
                int num = 30;
                System.out.println(?);
                System.out.println(?);
                System.out.println(?);
            }
        }
    
        public static void main(String[] args) {
            InnerClass in = new OuterClass().new InnerClass();
            in.show();
        }
    }
    

    1.num 2.this.num 3.OuterClass.this.num
    コードを補完し、コンソールに「HelloWorld」を出力する必要があります.
    interface InterfaceTest {
        void show();
    }
    
    public class TestClass {
    
        //    
    
        public static void main(String[] args) {
            TestClass.method().show();
        }
    }
    

    ....答え:
    interface InterfaceTest {
        void show();
    }
    
    public class TestClass {
    
        //    
        public static InterfaceTest method() {
            return new InterfaceTest() {
                @Override
                public void show() {
                    System.out.println("HelloWorld");
                }
            };
        }
    
        public static void main(String[] args) {
            TestClass.method().show();
        }
    }
    

    締めくくり
    学海は果てしなく、私たちは前に進むだけでなく、時々振り返って、来た道を見なければなりません.
    文の中にはお兄さんの文章を参考にして、リンクを添付しています.http://blog.csdn.net/d29h1jqy3akvx