匿名クラスについてのまとめ
匿名クラス (Anonymous Inner Classes) 概要
1. クラスの拡張
匿名クラスによって、インスタンス化時に拡張を実装することができる
構文
new クラス名() { // 変数の定義 private int variable = 5; // オーバーライド @Override toString() { ... } }
- インスタンスの生成と
{ ... }
ブロック内部でクラスの拡張を定義している
例1. Threadインスタンスの生成とrunメソッドのオーバーライド
ThreadメソッドはRunnableをimplementsしているので、生成時に匿名クラスを使ってOverrideする事ができる
public static void main(String[] args) { // Threadインスタンスの生成と Thread t = new Thread() { @Override public void run() { System.out.println("Child Thread"); } } t.start(); }
例2. Comparableをimplementsしているオブジェクトのソート操作を変更する
デフォルトでは rollNo
によってソートされる Student
クラスを実行時に名前順にソートするように変更させます。
Studentクラス
Comparableを実装しています。
static class Student implements Comparable<Student> { int rollno; String name; Student(int rollno, String name) { this.rollno = rollno; this.name = name; } // rollno順にソートされる public int compareTo(Student other) { return Integer.compare(this.rollno, other.rollno); } @Override public String toString() { return "rollno: " + this.rollno + " name: " + this.name; } }
匿名クラスによるStudentの拡張
匿名クラスを使ってクラスの拡張とインスタンスの生成を同時に行っています。
public static Student createStudent(int rollno, String name) { return new Student(rollno, name) { @Override public int compareTo(Student other) { // 名前順に変更 return this.name.compareTo(other.name); } }; }
実行結果
public static void main(String[] args) { var sato = createStudent(1, "sato"); var tanaka = createStudent(2, "tanaka"); var ando = createStudent(3, "ando"); var maeda = createStudent(4, "maeda"); var students = new Student[]{tanaka, sato, maeda, ando}; Arrays.sort(students); System.out.println(Arrays.toString(students)); // 実行結果 // [rollno: 3 name: ando, rollno: 4 name: maeda, rollno: 1 name: sato, rollno: 2 name: tanaka] }
Comparable vs Comparator
Comparableは、クラスが自然な順番を持っていることを示すインターフェースです。 したがって実行時にクラスが持つ自然な並びとは異なる順番にソートさせる場合は、Comparable ではなく java.util.Comparator を使ったほうが適切です。
2. インターフェースの実装
インターフェースに必要となるメソッドの実装を行い、そのままインスタンス化することができる。
構文
new インターフェース名() { // インターフェースに必要となるメソッドを実装 }
1. Runnableの実装とインスタンス化
public static void main(String[] args) { Thread t = new Thread(new Runnable() { public void run() { System.out.println("Child Thread"); } } t.start(); }
2. ActionListenerの実装とインスタンス化
JButton button = new JButton("Click Me!"); button.addActionListener(new ActionListener() { // 変数も定義できる private int iClickCount = 0; public void actionPerformed(ActionEvent e) { ((JButton)e.getSource()).setText(String.format("%d times Clicked", ++iClickCount)); } });
匿名クラスの特徴
- コンストラクタが存在しない
式
として評価される* 変数や関数の引数、返り値にわたすことができる
ラムダ式との関係
- 匿名クラスは
Java 7
で実装された - ラムダ式は
Java 8
で実装された@FunctionalInterface
に特化した匿名クラスの発展形