ある同僚が次のようなコードの意味を尋ねてきました:
MqMessage<MqMessageThink> mm = JSON.parseObject(message.toString(), <strong>new TypeReference<MqMessage<MqMessageThink>>() {}</strong>);
この赤太字部分は一体何を意味しているのでしょうか。
これは匿名クラスのインスタンスを生成しているコードです。
1. 匿名クラスの基本構文と用途
Javaにおける匿名クラスは、既存のクラスを継承あるいはインターフェースを実装しつつ、その場で新しいクラスを定義しインスタンス化する仕組みです。
一般的な構文は以下の通りです:
new クラス名またはインターフェース名() { /* 実装内容 */ }
この構文には3つの要素があります:
- newキーワード
- 親クラスまたはインターフェースのコンストラクタ
- { }内の実装ブロック
この3つを組み合わせることで、「名前のないクラスを定義して即座にインスタンス化する」処理が行われます。
例えば以下のように、インターフェースの実装や抽象クラスの具象化に用いることができます:
Runnable r = new Runnable() {
public void run() {
System.out.println("Hello from anonymous class!");
}
};
2. TypeReferenceを用いた具体例
冒頭のコードでは、FastJSONのTypeReferenceクラスを用いてジェネリクス型の情報を保持しています。
このクラスはprotectedなコンストラクタしか持たないため、直接インスタンス化することはできません。
そこで、以下のように匿名クラスとしてインスタンスを生成します:
new TypeReference<MqMessage<MqMessageThink>>() {}
この匿名クラスはTypeReferenceを継承し、ジェネリクスの型情報を保持する役割を果たします。
以下は簡略化したTypeReferenceのコンストラクタの一部です:
protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
this.type = type;
}
このコンストラクタでは、自身のジェネリクス情報を取得して保持しています。
3. 匿名クラスの利点と注意点
匿名クラスの主な用途・利点は以下の通りです:
- インターフェースや抽象クラスのインスタンスを簡単に作成できる
- 一時的に必要な処理を簡潔に記述できる
- ジェネリクス情報の保持や、特定のライブラリのAPI要件を満たす
ただし、以下のような注意点もあります:
- 再利用性が低いため、複数回利用が必要な場合は名前付きクラスにすべき
- デバッグや保守がやや困難になる