前回の記事では、インターフェースを使ってクラスの「型」を定義する方法を学んだよね。インターフェースを使えば、複数のクラスに共通の振る舞いを強制したり、疎結合なコードを書いたりできるんだった。
インターフェースの基本:契約を定義する | ToolDocs
今回は、そんなインターフェースや抽象クラスと相性抜群の、**「匿名クラス」**について深掘りしていくよ。名前からしてちょっと怪しげだけど、これがなかなかどうして、めちゃくちゃ便利なやつなんだ。
匿名クラスってなんだ?
まず、匿名クラスを一言で説明するなら、**「名前のない、一時的に使うためだけのクラス」って感じかな。通常のクラスは、class MyClass { ... }みたいに名前をつけて定義するよね。でも匿名クラスは、その場でサッと作って、一度使ったらおしまい!っていう、まさに「使い捨ての便利屋」**なんだ。
どんな時に使うかというと、
- インターフェースを実装するクラスを一時的に作りたい時
- 抽象クラスを継承するクラスを一時的に作りたい時
- イベントリスナーみたいに、特定の処理をその場で記述したい時
なんかに威力を発揮するよ。
匿名クラスの書き方
匿名クラスの基本的な書き方はこんな感じ。ちょっと特殊だから、じっくり見てみてね。
Java
// インターフェースの場合
InterfaceName instance = new InterfaceName() {
// インターフェースのメソッドを実装する
@Override
public void someMethod() {
// 処理
}
};
// 抽象クラスの場合
AbstractClassName instance = new AbstractClassName() {
// 抽象メソッドを実装する
@Override
public void someAbstractMethod() {
// 処理
}
// 必要であれば、他のメソッドもオーバーライドできる
};
ポイントは、new InterfaceName() { ... }とかnew AbstractClassName() { ... }って部分。普通のインスタンス化に見えるけど、その後に{ ... }が続いているのが匿名クラスの目印だよ。この波括弧の中に、インターフェースのメソッドを実装したり、抽象クラスの抽象メソッドをオーバーライドしたりするんだ。
例を見てみよう!
言葉だけだと分かりにくいから、具体的な例で匿名クラスの便利さを体験してみよう。
例1:シンプルな挨拶インターフェース
まずは、前回のインターフェースの話でも出てきたような簡単な例から。挨拶をするインターフェースを作ってみよう。
Java
// インターフェースの定義
interface Greeter {
void sayHello();
}
public class AnonymousClassExample1 {
public static void main(String[] args) {
// 匿名クラスを使ってGreeterインターフェースを実装
Greeter englishGreeter = new Greeter() {
@Override
public void sayHello() {
System.out.println("Hello!");
}
};
Greeter japaneseGreeter = new Greeter() {
@Override
public void sayHello() {
System.out.println("こんにちは!");
}
};
englishGreeter.sayHello(); // 出力: Hello!
japaneseGreeter.sayHello(); // 出力: こんにちは!
}
}
この例では、Greeterインターフェースを実装するクラスを、わざわざEnglishGreeterとかJapaneseGreeterみたいに名前をつけて作らなくても、その場でnew Greeter() { ... }という形で匿名クラスとして実装しているね。これは、**「この処理のためだけにちょっとだけGreeterを実装したいんだ!」**っていう時にすごく便利なんだ。

vscodeで実行した結果
もし匿名クラスを使わないなら、こんな感じでクラスを定義する必要があるよね。
Java
class EnglishGreeter implements Greeter {
@Override
public void sayHello() {
System.out.println("Hello!");
}
}
class JapaneseGreeter implements Greeter {
@Override
public void sayHello() {
System.out.println("こんにちは!");
}
}
public class AnonymousClassExample1_NoAnonymous {
public static void main(String[] args) {
Greeter englishGreeter = new EnglishGreeter();
Greeter japaneseGreeter = new JapaneseGreeter();
englishGreeter.sayHello();
japaneseGreeter.sayHello();
}
}
「英語の挨拶」と「日本語の挨拶」みたいに、別の振る舞いをさせたいけど、それぞれを独立したクラスとして定義するほどでもないな…って時に匿名クラスは輝くんだ。

vscodeで実行した結果
例2:ボタンのクリックイベント
匿名クラスがよく使われる場面の一つに、GUI(グラフィカルユーザーインターフェース)のイベント処理があるよ。例えば、ボタンがクリックされた時の処理なんかは、まさに匿名クラスの出番だ。
JavaFXやSwingといったGUIライブラリでは、ボタンにアクションを設定するために、特定のインターフェース(例えばActionListener)を実装したオブジェクトを渡すことが多いんだ。
Java
// 仮のGUIライブラリのイメージ (実際のJavaFXやSwingとは少し異なりますが、概念は同じです)
interface ActionListener {
void actionPerformed();
}
class Button {
private String label;
private ActionListener listener;
public Button(String label) {
this.label = label;
}
public void setActionListener(ActionListener listener) {
this.listener = listener;
}
public void click() {
System.out.println(label + "ボタンがクリックされました!");
if (listener != null) {
listener.actionPerformed();
}
}
}
public class AnonymousClassExample2 {
public static void main(String[] args) {
Button clickMeButton = new Button("Click Me");
// ボタンがクリックされた時の処理を匿名クラスで定義
clickMeButton.setActionListener(new ActionListener() {
@Override
public void actionPerformed() {
System.out.println("やった!ボタンが押されたよ!");
}
});
Button exitButton = new Button("Exit");
exitButton.setActionListener(new ActionListener() {
@Override
public void actionPerformed() {
System.out.println("アプリケーションを終了します...");
// 実際にはSystem.exit(0)などを行う
}
});
// ボタンをクリックしてみる
clickMeButton.click();
exitButton.click();
}
}
この例では、setActionListenerメソッドに、ActionListenerインターフェースを実装した匿名クラスを渡しているね。これによって、ボタンがクリックされた時に実行される処理を、その場でシンプルに書くことができるんだ。
もし匿名クラスを使わないとすると、ボタンごとに別々のクラスを作らないといけなくなって、コードがごちゃごちゃしちゃう可能性があるよね。

vscodeで実行した結果
例3:スレッドの実行処理
Javaで並行処理を行う「スレッド」を使う際にも、匿名クラスはよく登場するよ。Runnableインターフェースというものがあって、これを実装したクラスのrunメソッドに、スレッドで実行したい処理を書くんだ。
Java
public class AnonymousClassExample3 {
public static void main(String[] args) {
System.out.println("メインスレッド開始");
// 新しいスレッドで実行する処理を匿名クラスで定義
Thread myThread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("サブスレッド: " + i);
try {
Thread.sleep(100); // 100ミリ秒待つ
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
myThread.start(); // スレッドを開始
for (int i = 0; i < 5; i++) {
System.out.println("メインスレッド: " + i);
try {
Thread.sleep(150); // 150ミリ秒待つ
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("メインスレッド終了");
}
}
このコードを実行すると、「メインスレッド」と「サブスレッド」のメッセージが交互に出力されるはずだよ。ThreadクラスのコンストラクタにRunnableインターフェースを実装した匿名クラスを渡すことで、スレッドで実行したい処理をシンプルに定義できるんだ。

vscodeで実行した結果
匿名クラスの注意点
便利な匿名クラスだけど、いくつか注意点もあるよ。
- コンストラクタを持てない: 匿名クラスは名前がないから、コンストラクタを明示的に定義することはできないんだ。初期化が必要な場合は、フィールド初期化子やインスタンス初期化ブロックを使うことになるよ。
- 一度しかインスタンス化しない: 基本的に、匿名クラスは一度きりの使い捨て。何度も同じ処理を使い回したい場合は、通常のクラスとして定義する方がいい。
- 短いコードに使う: あまりに処理が複雑になったり、メソッドが多かったりすると、匿名クラスの可読性が落ちてしまう。シンプルで短い処理に限定して使うのがおすすめだよ。
- 外部のローカル変数にアクセスする場合: 匿名クラスの中から、それを囲むメソッドのローカル変数にアクセスする場合、そのローカル変数は実質的に
finalである必要があるよ(Java 8以降は明示的にfinalと書かなくても暗黙的にfinal扱いになることが多いけど、変更できない変数と覚えておくといい)。
まとめ
匿名クラスは、**「一時的にインターフェースを実装したり、抽象クラスを継承したりして、その場限りの処理を書きたい」**という時にめちゃくちゃ役立つ機能だ。特にイベント処理やスレッドなど、特定の振る舞いを簡潔に定義したい場面で真価を発揮するよ。
初めは少し特殊な書き方で戸惑うかもしれないけど、例を参考に何度も書いてみて慣れていこう! コードの量も減らせるし、可読性もアップするから、ぜひ使いこなしてみてね。


コメント