JAVAのジェネリックでnew T()とかnew T[]とか

とりあえずC#で書くならこういうのをやりたいとする。

class BaseModel<T> where T : new() {
    public T getModel() {
        return new T();
    }
    public T[] getModels() {
        return new T[10];
    }
}
class A : BaseModel<なんか適当なデフォルトコンストラクタを持つクラス> {
}

これがJavaでは出来ない。
正確には出来るけどえらい面倒くさかったのでメモ。


new T()

これは出来ない。

new T();

頑張れば出来る。

(T)instance.getClass().newInstance();

instanceは、T型のインスタンス。T型のインスタンスのクラス情報とって、newInstanceしてる。


えらくださいと思うんだけど、JAVA界隈ではメソッドの引数でインスタンス渡すってのが普通みたい。


new T[N]

JAVAだとT型の配列も作れない。

new T[countOfArray];

まあめっちゃ頑張れば出来る。

T[] array = (T[])java.lang.reflect.Array.newInstance(instance.getClass(), countOfArray);


やっぱりTのインスタンス必須(Tではない)。なんでもJavaは実行時にジェネリックの情報を扱えなくて、コンパイル時だけ扱うからしゃあないんだと。


ちなみにこの例で別の解としてListからtoArray使えばいいじゃんって話があるけど、俺にはでけんかったよ。
なぜならnew T[0]が出来ないので、ListのtoArrayに渡す引数が作れないから。当然メソッドの引数でTのインスタンスもらうなら可能だけど、型の解決なんてクラス内で解決しろよと思うので却下。
ということで内部的に解決するならArray.newInstance一択っぽい。





C#だとListとかでToArrayすれば勝手にタイプセーフになるけど、JAVAだとtoArray(new X[0])しないといけないとかいろいろうざい。後方互換がどうのと。思い切って切り捨てりゃいいのに、捨てないからどんどんグチャってんだろうな。


基本的な設計指針からして、例外もいちいちキャッチしないといけないから事になっとるからコードがぐんぐん長くなるし。
プロパティもねーし。
リフレクション使いまくるしかないから実行速度も気になるし。


やっぱ静的型付け言語ならC#最強って事で。
ま、仕事だから使いますけども。




※追記:本問題に関して、コメントに有益な追加情報があります。