The HIRO Says

If you smell what The HIRO is cooking!!!

generics で SuppressWarnings を使う

generics を使っていると、コンパイル時に色々な警告に遭遇します。
原則これらは簡単に除去できるんですが、中にはどうやるの?というケースもあります。
今回は、そういう特殊なケースについて記述します。


特殊な警告例

次のコードは、java.lang.List#get(int) と同じことを、無理やりメソッドにしたものです。
わざとらしく、List#toArray() とかを使っています。

    public static  E get(List list, int offset) {
        // エラーチェックロジックは省略

        E array = (E) list.toArray();

        return array[offset];
    }

これをコンパイルすると、次の警告が出てきます。
  型の安全性:Object から E へのキャストは、実際に消去された型 Object[] に対してチェックを行います。


警告の意味

generics の型チェックは、コンパイル時にのみ行います。
この型チェックの情報は、実行時には無くなってしまうという仕様になっています。
(「コンパイル時にチェックしているから十分でしょ」ということのようです。)


そのため、「”(E) list.toArray()”なんて書いているけれども、実際には Object が返されるよ、大丈夫!?」という意味の警告を、コンパイル時に出してくれているのです。


解決策

ことこのメソッドに関しては、引数が List ですから、型は保障できています。
なので、この警告は余計なおせっかいということになります。
そういう場合には、@SuppressWarning("unchecked") を使います。

    // 型が E であることが保障されている。
    public static  E get(List list, int offset) {

        // エラーチェックロジックは省略

        @SuppressWarnings("unchecked")
        E array = (E) list.toArray();

        return array[offset];
    }

SuppressWarnings の使いどころ

@SuppressWarnings("unchecked") は、generics の型チェックをある程度無効にする意味があるので、多用すると generics の効用を損なってしまいます。
なので、SuppressWarning は、以下のように使用しましょう。

  1. コード上型の安全性が保障できる場合にのみ使用する。
  2. 必要最小限のスコープで使用する。(メソッド全体、クラス全体での定義は避ける)


以下のようには定義しないようにしましょう。

    @SuppressWarnings("unchecked")
    public static  E get(List list, int offset) {

        // エラーチェックロジックは省略

        E array = (E) list.toArray();

        return array[offset];
    }