放課後プログラミング

調べたことや考えたことなどを忘れないために書きます。

ジェネリクスの使い方 2

前回(ジェネリクスの使い方 1)でジェネリクスの考え方と境界のある型パラメータについて理解できたので、この投稿ではワイルドカードについてまとめます。

class Utility {
    static ArrayList<?> getArr(boolean bool){
        return bool ? new ArrayList<String> : new ArrayList<Integer>;
    }
}

ワイルドカード<?>は実行されるまで型が不明であるものを表現することができる。この例ではメソッドが呼ばれた引数の値によって、ArrayList<String>型を返すかArrayList<Integer>型を返すか変わる。このように不定となっている型パラメータをワイルドカード<?>で表す。

この機能はジェネリクスを用いたクラスを使用するときに役に立つ。

class B<T extends Number> {
    private T num;
    public B(T num) { this.num = num; }
    public T getNum() { return num; }
}

class Utility {
    static int getNumAsInt(B<? extends Number> b){
        return b.getNum().intValue();
    }
}

ワイルドカードでも境界を設定することができて、上記のようにUtliityクラスを定義することでメソッドgetNumAsIntはNumber型又はそのサブクラス型に対応付けされたBクラスのインスタンスを引数に受けることができる。また、B#getNum()の返り値型TはNumber型又はそのサブクラス型であることが保証されているから、その返り値に対してintValue()メソッドを実行することができる。

もうひとつ例を示す。

class B<T> {
    private T t;
    public B(T t) { this.t= t; }
    public T getT() { return t; }
}

class Utility {
    static String getTStr(B<?> b){
        return b.getT().toString();
    }
}

<?>とはすなわち<? extends Object>と同義であるから、Objectクラスに実装されたtoString()は実行することができる。

これでジェネリクスの機能を全て説明できたわけではないけれど、ここまで書いた考え方で大体理解できると思います。



参考にさせて頂きました