The HIRO Says

If you smell what The HIRO is cooking!!!

generics のありがたみをコードで確認する

百聞は一見に如かず。
実際にコードを書いて、generics のありがたみを確認してみましょう。

generics を使用しない場合

    // String が入る想定のリストを定義する。
    List stringList = new ArrayList();

    // 値を追加してみる。
    stringList.add("1");    // String
    stringList.add(2);      // int

    // 値を抽出してみる。
    String str1 = (String) stringList.get(0);
    String str2 = (String) stringList.get(1);

このコードでは、String str2 = (String) stringList.get(1)ClassCastException が発生します。
ただ、エラーが発覚するタイミングが問題。
コンパイル時には何も出ないのに、実行時にエラーが出てきます。
今回のような簡単なプログラムならばすぐに原因を見つけられるでしょうが、これが S2 を使ったり深いネストだったりすると…なかなか解決し辛いと思います。

generics を使用する場合

    // String が入る想定のリストを定義する。
    List stringList = new ArrayList();

    // 値を追加してみる。
    stringList.add("1");    // String
    stringList.add(2);      // int

    // 値を抽出してみる。
    String str1 = stringList.get(0);
    String str2 = stringList.get(1);

このコードでは、stringList.add(2)コンパイルエラーが発生します。
【エラー】型 List のメソッド add(int, String) は引数(int) に適用できません。
同じバグでも、generics だとコンパイル時にこれを検知してくれます。
なので、generics を使わない場合よりはバグ FIX が早く確実に行えます。


また併せて、generics を使っているとキャストが不要になるので、stringList.get() が簡単になっています。

補足

Collection に generics を使うことで、以下のように for 文を若干簡単にできるようになります。

(1)foreach
    for (String temp : stringList) {
        System.out.println(temp);
    }
(2)値の直接取得
    for (int i = 0; i < stringList.size(); i++) {
        String temp = stringList.get(i);
        System.out.println(temp);
    }
(3)generic な iterator(next() でキャストが不要)
    for (Iterator iterator = stringList.iterator(); iterator.hasNext();) {
        String temp = iterator.next();
        System.out.println(temp);
    }