2017-02-15 4 views
2

私はこのような何かをしようとしています:Javaのジェネリックリスト<>

1.アプローチ

Type ty = entityType.getEntityClass(); // could be e.g. String.class 
List<ty> list; 

2.アプローチ

Class cl = entityType.getEntityClass(); // could be e.g. String.class 
List<cl> list; 

はしかし、コンパイラは、単純に言います"いいえ"。

ジェネリックタイプ<T>を設定する方法はありますか。たとえばjava.util.Listを持つことによってのみjava.util.Listの動的String.classまたはfoo.getClass()

...

私は実際にタイプEntityTypeEnumの特定のパラメータでリストを初期化してやろうとしていますか、それはClassプロパティ値です。

public enum EntityTypeEnum { 
    ARTICLE(Article.class), 
    ORDER(OrderHeader.class), 
    CUSTOMER(Customer.class), 
    CUSTOMER_SESSION(CustomerSession.class); 

    private final Class entityClass; 

    private EntityTypeEnum(final Class entityClass) { 
     this.entityClass = entityClass; 
    } 

    public Class getEntityClass() { 
     return entityClass; 
    } 
} 

建設的な批判を歓迎します。 ありがとうございました!

追加:(アンディさんのコメントの回答など)

Class cl = String.class; 
List<cl> list; 

のいずれかに動作していない..is!

List<String> list; 

です。

StringString.classの違いは何ですか?

などの値を設定する方法があります:あなたは、Javaのジェネリックが可能であるか誤解されている

public enum EntityTypeEnum { 
    ARTICLE(Article) 
.. 
+4

はありません「しかし、コンパイラは、単純に言います 『』。」それはジェネリックが何のためではないからです。コンパイル時に型の安全性を強制するためのものです。実行時まで型を知らなければ、ジェネリックはあなたを助けません。 –

+0

私はあなたの意見を持っています。コンパイル時にその型がよくわかっているとします:Class cl = String.class;リストリスト; まだコンパイルされませんでした。 –

+0

技術的には、これはコンパイル時定数式ではありません。しかし、単純にこれを行うことはできません。ジェネリックは*変数*に基づくのではなく、変数の*タイプ*に基づくことができます。 –

答えて

1

ジェネリックスはコンパイル時のコンセプトですが、ランタイムコンセプトとして使用しようとすると動作しません。

違いは、コンパイル時の概念では、コンパイラは、コード上にある情報(実行中または評価なし)に基づいて型を把握できる必要があります。

ここにこのコードは、構文的に正しいようになります:

public enum EntityTypeEnum 
{ 
    ARTICLE(String.class), // just using some builtin types to demonstrate 
    ORDER(Integer.class), 
    CUSTOMER(Double.class), 
    CUSTOMER_SESSION(Short.class); 

    private final Class<?> entityClass; 

    private EntityTypeEnum(final Class<?> entityClass) 
    { 
    this.entityClass = entityClass; 
    } 

    public Class<?> getEntityClass() 
    { 
    return this.entityClass; 
    } 
} 

class Test 
{ 
    // here, T is the type parameter which is determined from the class type 
    public <T> List<T> createList(final Class<T> clazz) 
    { 
    return new ArrayList<T>(); 
    } 

    // this is the demo code on how to use it  
    public void foo() 
    { 
    EntityTypeEnum t = EntityTypeEnum.ARTICLE; 
    List<?> list = createList(t.getEntityClass()); 
    } 
} 

問題は、これがずっとあなたを助けにはならないということです。リストは、リストとほぼ同じです。コンパイラは、実行時に依存するため、型を特定の包含オブジェクトクラスに絞り込むことはできません。あなたのケースでは

、あなたの要素に共通のスーパークラスを持っている場合、あなたはタイプ絞り込むためにこの情報を使用することができます。

public enum EntityTypeEnum 
{ 
    ARTICLE(Article.class), 
    ORDER(OrderHeader.class), 
    CUSTOMER(Customer.class), 
    CUSTOMER_SESSION(CustomerSession.class); 

    private final Class<? extends CommonParent> entityClass; 

    private EntityTypeEnum(final Class<? extends CommonParent> entityClass) 
    { 
    this.entityClass = entityClass; 
    } 

    public Class<? extends CommonParent> getEntityClass() 
    { 
    return this.entityClass; 
    } 
} 

class Test 
{ 
    public <T extends CommonParent> List<T> createList(final Class<T> clazz) 
    { 
    return new ArrayList<T>(); 
    } 

    public void foo() 
    { 
    EntityTypeEnum t = EntityTypeEnum.ARTICLE; 
    List<? extends CommonParent> list = createList(t.getEntityClass()); 
    } 
} 

をしかし、あなたは、共通の親を持つ場合、の何のメリットがありませんがただ書きかけ上記のコードは:

List<CommonParent> list = new ArrayList<CommonParent>(); 

とすべてが、追加の一般的なものを飛ばして...

4

は:あなただけで、変数のに基づいて何かをすることはできません変数のタイプ

基本的に、Javaジェネリックはキャストの単なるエッセンスです。コンパイラによって自動的にキャストが挿入され、キャストの結果のタイプが一致するかどうかがチェックされます。


あなたの例では、列挙型を使用せずにソートすることもできます。 Javaのenumの欠点の1つは、すべての要素が同じ型であることです。あなたは今、あなたが記述した方法でこれらを使用することができます

final class EntityTypeEnumIsh { 
    private EntityTypeEnumIsh() {} 

    static final EntityClassSupplier<Article> ARTICLE = 
    new EntityClassSupplier<>(Article.class); 
    static final EntityClassSupplier<OrderHeader> ORDER = 
    new EntityClassSupplier<>(OrderHeader.class); 
    // ... 

    final class EntityClassSupplier<T> { 
    private final Class<T> clazz; 

    EntityClassSupplier(Class<T> clazz) { this.clazz = clazz; } 

    Class<T> getEntityClass() { return clazz; } 
    } 
} 

<T> List<T> method(EntityClassSupplier<T> supplier) { 
    return new ArrayList<>(); 
} 

をして呼び出す代わりに、実際の列挙型を使用しての

、あなたはおおよそ列挙型のようなものを使用することができます

List<Article> list = method(EntityTypeEnumIsh.ARTICLE); 

もちろん、「実数」列挙型のniceness(シリアル化、r反射攻撃に対する抵抗など)。しかし、何か役に立つものがあるので、あなたのユースケースに合わせて検討してください。

関連する問題