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 とか使って生成していかないといけないんだろうなあ。でも、引数はどこから持ってくるんだ? なんてことを考えると、「やっぱクローンでも良いんじゃね?」とか思える。
どっかに良いお作法が転がってないかなあ…。