ジェネリクスのインスタンスを生成する方法

java でジェネリクス(総称型)のインスタンスを生成するには、どうするのか悩んでいる土曜日の昼下がり。

例えば、次のようにメソッドの総称型を定義してみる。

public  T add(T date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);
    return (T) calendar.getTime();
}

これだと、引数に java.util.Date を渡した場合は問題ないが、そのサブクラスである java.sql.Date なんかを渡すと、最後の総称型へのキャストで、ClassCastException でコケてしまう。そりゃそうだ。

同じ型のインスタンスを生成できれば、そこに値を詰めて返せるんだけど、総称型はその名のとおりクラス名を特定できないから、さて困った。

T result = new T();

みたいなことができれば良いんだけど、当然できるわけもなく。それじゃあ、と思って次に試したのがコレ。

public  T add(T date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);

T result = date.clone(); result.setTime(calendar.getTimeInMillis());
return result; }

型が分からないなら、もうクローンしちゃえば良いんじゃね、と。これは確かに動くのだけど、いやいやインスタンスを生成するのと、クローンするのでは意味が違う。

public  T add(T date) throws Exception {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);

T result = date.getClass().newInstance(); result.setTime(calendar.getTimeInMillis());
return result; }

ということで、今のところ、これが一番しっくり来てる。

このケースだと java.util.Date のサブクラス限定だから、このくらいで良いけど、もっと汎用化するなら、newInstance() じゃなくて Constructor とか使って生成していかないといけないんだろうなあ。でも、引数はどこから持ってくるんだ? なんてことを考えると、「やっぱクローンでも良いんじゃね?」とか思える。

どっかに良いお作法が転がってないかなあ…。

このエントリーのトラックバックURL
http://www.deftrash.com/admin/mt4/mt-tb.cgi/473