Javaの匿名クラスとその応用

ある同僚が次のようなコードの意味を尋ねてきました:

MqMessage<MqMessageThink> mm = JSON.parseObject(message.toString(), <strong>new TypeReference<MqMessage<MqMessageThink>>() {}</strong>);

この赤太字部分は一体何を意味しているのでしょうか。

これは匿名クラスのインスタンスを生成しているコードです。

1. 匿名クラスの基本構文と用途

Javaにおける匿名クラスは、既存のクラスを継承あるいはインターフェースを実装しつつ、その場で新しいクラスを定義しインスタンス化する仕組みです。

一般的な構文は以下の通りです:

new クラス名またはインターフェース名() { /* 実装内容 */ }

この構文には3つの要素があります:

  1. newキーワード
  2. 親クラスまたはインターフェースのコンストラクタ
  3. { }内の実装ブロック

この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要件を満たす

ただし、以下のような注意点もあります:

  • 再利用性が低いため、複数回利用が必要な場合は名前付きクラスにすべき
  • デバッグや保守がやや困難になる

タグ: Java 匿名クラス ジェネリクス fastjson TypeReference

7月10日 00:00 投稿