Java の匿名内部クラス
この記事では、Java の AnonymousInner クラスとその有用性について説明します。
Java の匿名内部クラス
匿名という言葉は、名前が不明なことを意味します。同じことが Java 匿名内部クラスにも当てはまります。
名前がなく、単一のオブジェクトを作成するだけでよい内部クラスは、Java 匿名内部クラスと呼ばれます。クラスやインターフェイスからメソッドをオーバーロードするなど、追加の操作を行う必要がある場合に、オブジェクトのインスタンスを作成する必要がある場合に便利です。
これを行うには、クラスのサブクラスを作成せずに、Java の匿名内部クラスを使用します。
つまり、名前のないクラスは、Java 匿名内部クラスと呼ばれます。通常、新しいクラスを作成するときはいつでも、そのクラスに名前が付けられます。
したがって、Java 匿名内部クラスは、新しいクラスの作成には使用されません。むしろ、クラスまたはインターフェースのメソッドをオーバーライドするために使用します。
これらは、リスナーインターフェイスの実装クラスを作成するグラフィックプログラミングでも役立ちます。
Java 匿名内部クラスの構文は、クラス定義がコードのブロック内にも存在することを除いて、コンストラクターの呼び出しに似ています。
構文:
Demo d = new Demo() {
public void demo_method() {
// definition
}
};
ここで、demo
は抽象/具体的なクラスまたはインターフェースを指します。匿名内部クラスの概念をよりよく理解するために、通常の Java クラスとの違いを見てみましょう。
- 通常のクラスを使用して任意の数のインターフェイスを実装できますが、匿名の内部クラスは一度に 1つのインターフェイスのみを実装します。
- 通常のクラスは、別のクラスを拡張し、同時に複数のインターフェースを実装できます。一方、匿名の内部クラスは、一度にこれらの 1つしか実行できません。
- コンストラクターの名前は、クラスの名前と同じです。これは、通常のクラスに任意の数のコンストラクターを記述できることを意味しますが、これは匿名の内部クラスには当てはまりません。
Java の内部クラスの詳細については、このドキュメントを参照してください。
Java の匿名内部クラスの変数とメンバー
匿名の内部クラスも、Java のローカルクラスと同じように変数をキャプチャします。ローカル変数へのアクセスは、囲んでいるクラスと同じです。
囲んでいるクラスのメンバーは、匿名クラスからアクセスできます。ただし、final ではないローカル変数(それを囲むスコープに存在する変数でさえも)にアクセスすることはできません。
さらに、匿名クラスで任意の型を宣言すると、そのスコープで同じ名前を持つ他の宣言がシャドウされます。匿名内部クラスにもいくつかの制限があります。
- 匿名内部クラスでは、静的初期化子またはメンバーインターフェイスの宣言は許可されていません。
- 静的メンバーは、定数変数の場合、匿名クラスの一部になることができます。
これで、匿名クラス内でフィールド、追加のメソッド、インスタンス初期化子、およびローカルクラスを宣言できると結論付けられます。
Java での匿名内部クラスの作成
匿名の内部クラスを作成するために使用できる主な方法は 2つあります。これらには、以下の使用が含まれます。
- クラス(抽象または具体的)
- インターフェース
それらを一つずつ見ていきましょう。
Java でクラスを使用して匿名の内部クラスを作成する
まず、以下の例を見てください。
abstract class Demo {
abstract void demo();
}
class AnonymousDemo {
public static void main(String args[]) {
Demo d = new Demo() {
void demo() {
System.out.println("This is a demo of an anonymous inner class using class.");
}
};
d.demo();
}
}
出力:
This is a demo of an anonymous inner class using class.
ここでは、コンパイラによって名前が決定されるクラスが作成されます。このクラスは、Demo
クラスを拡張し、demo()
メソッドを実装します。
匿名クラスのオブジェクトは d
です。これは、匿名型のデモ
クラスの参照変数です。コンパイルのためにこれを AnonymousDemo.java
として保存することに注意してください。
以下のコードは、コンパイラが内部クラスを生成する方法です。
import java.io.PrintStream;
static class AnonymousDemo$1 extends Demo {
AnonymousDemo$1() {}
void demo() {
System.out.println("This is a demo of an anonymous inner class using class.");
}
}
Java でインターフェイスを使用して匿名の内部クラスを作成する
上記のセクションでは、クラスを使用します。ただし、ここでは、匿名内部クラスのインターフェースを使用します。例を使ってこれを理解しましょう。
interface Demonstration {
void demo();
}
class AnonymousDemo {
public static void main(String args[]) {
Demonstration d = new Demonstration() {
public void demo() {
System.out.println("This is an example of an anonymous inner class using an interface.");
}
};
d.demo();
}
}
出力:
This is an example of an Anonymous inner class using an interface.
ここでは、コンパイラによって名前が決定されるクラスが作成されます。このクラスは、インターフェイス Demonstration を実装し、demo()
メソッドの実装を提供します。
匿名クラスのオブジェクトは d
です。デモンストレーションタイプの参照変数です。コンパイルのためにこれを AnonymousDemo.java
として保存することに注意してください。
以下のコードは、コンパイラが内部クラスを生成する方法です。
import java.io.PrintStream;
static class AnonymousDemo$1 implements Demonstration {
AnonymousDemo$1() {}
void demo() {
System.out.println("This is an example of an anonymous inner class using an interface.");
}
}
Java のさまざまなタイプの匿名内部クラス
匿名内部クラスは、宣言と動作に基づいて 3つのタイプに分類されます。
- クラスを拡張する匿名の内部クラス。
- インターフェイスを実装する匿名の内部クラス。
- 匿名内部クラスは、メソッド/コンストラクター引数内で定義されます。
これら 3つのタイプすべてについて 1つずつ説明しましょう。
Java でクラスを拡張する匿名の内部クラス
Thread クラスを拡張することでスレッドを作成できます。また、クラスを拡張する匿名の内部クラスを持つこともできます。
ここでは new
キーワードを使用して、親クラスタイプを参照するオブジェクトを作成します。以下の例を見てください。
class Demo {
public void example() {
System.out.println("Types of Anonymous classes");
}
}
public class AnonymousDemo {
public static void main(String args[]) {
Demo d1 = new Demo();
d1.example();
Demo d2 = new Demo() {
@Override
public void example() {
System.out.println("Type - 1");
}
};
d2.example();
}
}
出力:
Types of Anonymous classes
Type - 1
Java でインターフェイスを実装する匿名の内部クラス
Runnable インターフェースを実装することでスレッドを作成でき、anonymous
内部クラスもインターフェースを実装できます。new
キーワードを使用して、インターフェイスタイプを参照する匿名の内部クラスオブジェクトを作成します。
interface Demo {
public void demo();
}
public class AnonymousDemo {
public static void main(String args[]) {
Demo d = new Demo() {
@Override
public void demo() {
System.out.println("Type - 2");
}
};
d.demo();
System.out.println(d.getClass().getName());
}
}
出力:
Type - 2
AnonymousDemo$1
Java のメソッド/コンストラクター引数内の匿名内部クラス
メソッドまたはコンストラクター引数内の匿名内部クラスは、GUI
(グラフィカルユーザーインターフェイス)アプリケーションで使用されます。ここでは、匿名の内部クラスを引数として使用し、それをメソッドまたはコンストラクターに渡します。
これが例です。
abstract class Demo {
public abstract void demo();
}
class Example {
public void example(Demo d) {
d.demo();
}
}
public class AnonymousDemo {
public static void main(String args[]) {
Example e = new Example();
e.example(new Demo() {
@Override
public void demo() {
System.out.println("Type - 3");
}
});
}
}
出力:
Type - 3
Java の匿名内部クラスの利点
匿名の内部クラスは、メソッドのローカル変数を閉じます。これは、内部クラスよりも優れています。さらに、これらのクラスは冗長性を減らし、再利用性を提供します。
また、これらのクラスは、開発者がすべてのクラスの名前を自分で見つける必要がないため、開発者を支援します。匿名の内部クラスを同時に使用して、クラスの宣言とインスタンス化を行うことができます。
全体として、匿名内部クラスは Java の利点の 1つです。
Java の匿名内部クラスの詳細については、このドキュメントを参照してください。
まとめ
この記事では、Java の匿名内部クラスについて説明しました。通常のクラスと匿名の内部クラスの違いがわかりました。
また、Java 匿名内部クラスの使用法と利点についても説明しました。さらに、コードと例を通じて実装と構文を理解しました。さまざまなタイプの Java 匿名内部クラスについても学びました。
結論として、Java の匿名内部クラスは、再利用性を提供し、言葉遣いを減らすことによって、言語の機能と汎用性を追加します。