2011-07-06 15 views
7

相当するC#コードのJavaコードを書きたいと思います。私のコードのJava:型が型パラメータであるオブジェクトを作成します。

public abstract class A<T> where T : A<T>, new() 
{ 
    public static void Process() 
    { 
     Process(new T()); 
    } 

    public static void Process(T t) 
    { 
     // Do Something... 
    } 
} 

public class B : A<B> 
{ 
} 

public class C : A<C> 
{ 
} 

のJava等価では次のようになります。次のように

私のC#コードです。クラス宣言の力でここ

public abstract class A<T extends A<T>> 
{ 
    public static <T extends A<T>> void process() 
    { 
     process(new T()); // Error: Cannot instantiate the type T 
    } 

    public static <T extends A<T>> void process(T t) 
    { 
     // Do Something... 
    } 

    public class B extends A<B> 
    { 
    } 

    public class C extends A<C> 
    { 
    } 
} 

「新しい()」構文は、基本クラスから「新しいT()」を呼び出すことが可能になり、デフォルトの建設業者を書くためのクラスを派生しました。言い換えれば、基本クラスをwrtingしているとき、私は基本クラスから派生クラスオブジェクトをインスタンス化できるように、派生クラスにデフォルトコンストラクタがあることを確信しています。 Javaで

私の問題は、私はスーパークラスから派生したクラスのオブジェクトをインスタンス化することはできません。 "new T()"の呼び出しで"Cannot instantiate the type T"エラーが発生します。 JavaでC#と似たような方法がありますか?プロトタイプのパターンやクローニングのようなものを使うべきですか?

答えて

5

Javaはreified genericsをサポートしていないため、「new T();」と同等のものはありません。私がこれを回避する方法は、型トークンに対するリフレクションを使用することです。タイプトークンは、ジェネリックタイプが何であるかを示します。

public abstract class A<T> { 
    private Class<T> typeToken; 
    // constructor 
    public A() { 
     typeToken = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 
} 

次に、リフレクションを使用してクラスをインスタンス化します。それは醜いですが、それは仕事を完了します。あなたがジェネリックを使用している場合

+0

お返事ありがとうございます。私は静的メソッド内に新しいインスタンスを作成しようとしているので、getClass()を呼び出すことはできません。 T.classの他にコンパイル時の構築が存在しません。だから、反射は私のための解決策のようには見えません。または、私はそれをまだ見つけられませんでした(: –

+0

サブクラスが 'public class B extends A 'のサブクラスであれば、これはまったく同じ問題です。型トークンを使用するほうが、呼び出し側にトークンをコンストラクタまたはメソッドに渡すように要求する方がよい –

0

また、これには注意してください。

これは、配列に対してArrayListを好む理由の1つです。この問題の原因は、訂正可能性とタイプ消去にあります。

2

あなたはthis li nk - comparing java and C# genericsからC#​​とJavaでのジェネリック医薬品との差のいくつかの説明を見つけることができます。

のJavaのジェネリックは完全にコンパイル時の構文です。ランタイム情報には何も依存しないジェネリック型パラメータでは何もできません。これには、ジェネリック型 パラメータのインスタンスを作成

  • を。
  • ジェネリック型の配列を作成する パラメータ。
  • ジェネリック型パラメータのランタイムクラスをキシに。
  • instanceofにジェネリックタイプ パラメータを使用する。

java.lang.reflectネームスペースでこの制限を回避できます。 Genercs and Class.forName()

0

ちょうど沼地標準Abstract Factoryパターンを使用します。たとえば、このstackoverflowの質問を参照してください。特定のタイプに束縛されていないという追加の利点が得られます。実装タイプには特定のコンストラクタがなくても、インスタンスにはいくつかのパラメータ化、インスタンスのキャッシュなどが可能です。

神の愛のために、反射を使用しないでください。

0

他のコメントに加えて、私はジェネリックを使用しないことをお勧めします。彼らは必要ありません - とにかくコンパイル時に取り除かれます。あなたがそれらをよく知らないのであれば、できないことをやろうとします。

クラスが正常に動作したら、に戻してください。その時点で、IDEは便利で分かりやすいアドバイスを多く提供します。間違ったクラス。

終了したら、このクラスではジェネリックスがまったく必要ないように見えます。 (私はこのクラスで何ができるのかわかりませんが、静的メソッドの使用を理解していません - 個々のインスタンスの型情報にアクセスすることは決してありません)

0

実際これは問題ではありませんJava。イディオムがクラスを通過しています

public static <T extends A<T>> T process(Class<T> clazz) 
    { 
     T o = clazz.newInstance(); 
     process(o); 
     return o; 
    } 

    X x = process(X.class); // not too verbose 

一般的な例を示すために戻り値を追加しました。

関連する問題