CodeGym /Java Blog /ランダム /匿名クラス
John Squirrels
レベル 41
San Francisco

匿名クラス

ランダム グループに公開済み
やあ!今日のレッスンでは、引き続きネストされたクラスのトピックを検討していきます。ここで、最後のグループである匿名内部クラスの時間です。図に戻りましょう。 匿名クラス - 2前回のレッスンで説明したローカル クラスと同様、匿名クラスは一種の内部クラスです。また、いくつかの類似点と相違点もあります。しかし最初に、なぜ彼らは「匿名」と呼ばれているのでしょうか? これに答えるために、簡単な例を考えてみましょう。常に実行されて何かを行う基本的なプログラムがあると想像してください。いくつかのモジュールで構成されるこのプログラムの監視システムを作成したいと考えています。1 つのモジュールはパフォーマンスの一般的な指標を追跡し、ログを維持します。2 つ目は、エラーをエラー ログに登録して記録します。3 つ目は、不正なアクセス試行やその他のセキュリティ関連などの不審なアクティビティを追跡します。3 つのモジュールはすべて、本質的には単にプログラムの先頭から開始してバックグラウンドで実行する必要があるため、

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 つの具体的なクラスがそれを実装します。

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
すべてが順調に進んでいるように見えます。いくつかのモジュールで構成されるかなり一貫したシステムがあります。それぞれに独自の動作があります。新しいモジュールが必要な場合は、実装が非常に簡単なインターフェイスを備えているため、モジュールを追加できます。しかし、監視システムがどのように機能するかを考えてみましょう。 基本的に、 、、の 3 つのオブジェクトを作成し、それぞれのオブジェクトに対してメソッドを呼び出す匿名クラス - 3だけです。つまり、3 つのオブジェクトを作成し、それらに対して 1 つのメソッドを呼び出すだけです。 GeneralIndicatorMonitoringModuleErrorMonitoringModuleSecurityModulestartMonitoring()

public class Main {

   public static void main(String[] args) {

       GeneralIndicatorMonitoringModule generalModule = new GeneralIndicatorMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
コンソール出力:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
そして、これほど少ない作業で、システム全体 (3 つのクラスと 1 つのインターフェイス) を作成できました。これらはすべて、6 行のコードを実現するためのものです。一方、私たちの選択肢は何でしょうか?そうですね、これらの「1 回限り」のクラスを作成するのはあまりクールではありません。しかし、どうすればこれを修正できるでしょうか? ここで、匿名の内部クラスが私たちを助けてくれます。私たちの場合は次のようになります。

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
何が起こっているのか見てみましょう! インターフェイス オブジェクトを作成しているようです。

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
しかし、インターフェイス オブジェクトを作成できないことは以前から知られていました。そしてそれは不可能です。実際、それは私たちがやっていることではありません。書くとき:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Java マシン内では次のことが起こります。
  1. インターフェースを実装する名前のない Java クラスが作成されますMonitoringSystem
  2. コンパイラーがそのようなクラスを認識すると、インターフェースのすべてのメソッドを実装する必要がありますMonitoringSystem(これを 3 回実行しました)。
  3. このクラスのオブジェクトが 1 つ作成されます。コードに注意してください。

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
最後にセミコロンが付いています!そこには理由があります。同時にクラスを宣言し (中括弧を使用)、そのインスタンスを作成します ( を使用();)。3 つのオブジェクトはそれぞれ、startMonitoring()独自の方法でメソッドをオーバーライドします。最後に、それぞれに対してこのメ​​ソッドを呼び出すだけです。

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
コンソール出力:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
それでおしまい!目的は達成されました。3 つのMonitoringSystemオブジェクトを作成し、3 つの異なる方法でメソッドをオーバーライドし、それを 3 回呼び出しました。3 つのモジュールはすべて正常に呼び出され、実行されています。同時に、プログラムの構造もはるかにシンプルになりました。結局のところ、GeneralIndicatorMonitoringModuleErrorMonitoringModule、およびSecurityModuleクラスをプログラムから完全に削除できるようになりました。私たちは単にそれらを必要としていません - 私たちはそれらなしで素晴らしい仕事をしました。 それぞれの匿名クラスに異なる動作が必要な場合、たとえば、他のクラスにはない独自のメソッドなど、簡単に追加できます。

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
Oracle のドキュメントには、「ローカル クラスを 1 回だけ使用する必要がある場合は、[匿名クラス] を使用する」という優れた推奨事項が記載されています。匿名クラスは完全な内部クラスです。したがって、静的変数やプライベート変数を含む外部クラスの変数にアクセスできます。

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
これらはローカル クラスと共通点があります。つまり、宣言されているメソッド内でのみ表示されます。上の例では、errorModuleメソッドの外でオブジェクトにアクセスしようとするとmain()失敗します。そして、匿名クラスがその「祖先」 (内部クラス) から継承するもう 1 つの重要な制限があります。 それは、匿名クラスには静的変数と静的メソッドを含めることができません。上記の例では、getCurrentErrorCount()メソッドを静的にしようとすると、コンパイラはエラーを生成します。

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
静的変数を宣言しようとすると、同じ結果が得られます。

MonitoringSystem errorModule = new MonitoringSystem() {

   // Error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
そして今日のレッスンも終わりました!しかし、ネストされたクラスの最後のグループを調査しましたが、このトピックはまだ終了していません。ネストされたクラスについてさらに何が分かるでしょうか? きっとすぐに分かりますよ!:)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION