Effective Javaを読むチャレンジ-項目24-

項目24 無検査警告を取り除く

ジェネリックスを使用していると様々な警告が出ますが、そのうちの無検査警告についてピックアップした話です。

本書では無検査キャスト警告、無検査メソッド呼び出し警告、無検査ジェネリック配列生成警告、無検査変換警告を挙げているので、これらをまとめて無検査警告と称しているのだと思います。

それぞれの例を挙げてみます。まず無検査キャスト警告というのは次のようなものです。

原型からジェネリック型へキャストを行っています。コンパイル結果は下の通り。

Eclipseでは「型の安全性: List から List<String> への未検査キャスト」という警告が出ます。その修正方法は、原型をジェネリック型に変えることです。

次に無検査メソッド呼び出し警告です。原型のインスタンスがもつ、仮型パラメータを引数に持つメソッドを呼び出しています。

コンパイル結果です。

Eclipseでは「型の安全性: メソッド add(Object) は raw 型 List に属しています。総称型 List<E> への参照はパラメーター化される必要があります」という警告が出ます。その修正方法は、やはり原型をジェネリック型に変えることです。

無検査ジェネリック配列生成警告ですが、例えばリストをいくつか結合するようなメソッドを下記のように作ったとします。

コンパイルすると以下のような警告が出ます。

可変長引数をもつメソッドを呼び出す場合、その可変長の引数は実行時に配列として生成されます。そのせいで出てくる警告ですね。Eclipseでは「型の安全性: List<T> の総称配列は可変引数パラメーターに対して作成されます」と警告が表示されます。この修正は可変長引数を止めて、ListのListを1つ持つメソッドに変えることぐらいしかないと思います。

最後に無検査変換の例です。

原型からジェネリック型へ代入しようとしています。コンパイル結果です。

Eclipseでは「型の安全性: 型 ArrayList の式は、未検査の型変換を使用して List<String> に準拠するようにする必要があります」と警告が出ます。こちらも原型をジェネリック型に変えることで修正します。

取り除くことが可能なすべての無検査警告を取り除くこと

この項目の主題ですね。無検査警告は無視せず、後述する警告の抑制を行わず、できる限り取り除く。そうしないと、実行時にClassCastExceptionが発生するということです。そうして型安全が保証されれば、そのコードも安心して使えるでしょう、と。

一応、この項目で挙げられていた4パターンの無検査警告の修正方法も記述しておきました。

警告を取り除くことができなくて、警告を起こしているコードが型安全だと明確に示すことができる時に(限り)、警告を抑制すること

どうしても警告を取り除けない場合も多々あります。その場合は、@SuppressWarnings(“unchecked”)アノテーションで警告を抑制することができます。@SuppressWarnings(“unchecked”)アノテーションはクラスやメソッドから変数まで様々な粒度で使用できます。そしてそのアノテーションのスコープは最小限にすべきです。そして@SuppressWarnings(“unchecked”)アノテーションを使用するときには、そうするのが安全である理由を述べるコメントを必ず追加するとのことです。

無検査警告が安全である理由としては、本書の例のように引数を使って引数と同じ型にキャストしているから型安全と言える、などあると思います。現場で嫌というほど無検査警告見てきたはずなんですが、特にコード思い出しませんね・・・。条件反射的に警告を抑制するんじゃなく、まずはしっかり取り除いていきましょう。

広告
  • LINEで送る