2016-03-13 9 views
6

タイプパラメータを持つクラスを初期化する際に問題が発生しました。これはJavaの型推論の欠点であると思われます。これを回避する方法やこれを実現する方法があるかどうかを知りたいと思います。タイプパラメータを持つJava発行初期化クラス

コンストラクタサービス< ChildModel、ArrayListの< ChildModel >>(クラス< ChildModel>、クラス< ArrayListには>)

未定義です:

コンパイル時エラーがBusinessLogic::someLogic()である

public class ParentModel {} 

public class ChildModel extends ParentModel {} 

public class Service<E extends ParentModel, T extends Collection<E>> { 
    private Class<T> classOfT; 
    private Class<E> classOfE; 

    public Service(Class<E> classOfE, Class<T> classOfT) { 
     this.classOfE = classOfE; 
     this.classOfT = classOfT; 
    } 
} 

public class BusinessLogic { 
    public void someLogic() { 
     Service<ChildModel, ArrayList<ChildModel>> service = new 
      Service<ChildModel, ArrayList<ChildModel>>(ChildModel.class, ArrayList.class); 
    } 
} 

Java 7にコンパイル。

+0

「クラス」のフィールドやフィールドのタイプが「T」と「E」の場合はどうしたらいいですか? –

答えて

2

Javaのジェネリックは「消去」によって実装されているため、Class<ArrayList<ChildModel>>>はなく、Class<ArrayList>のみです。

あなたができることは、スーパータイプを許可することです。

Class<? super T> classOfT; 
Class<? super E> classOfE; 
public Service(Class<? super E> classOfE, Class<? super T> classOfT) { 

代わりに、あなたはクラスダブルキャストすることができます:

Class<ArrayList<Integer>> clazz = 
    (Class<ArrayList<Integer>>) (Class<? super ArrayList>) 
    ArrayList.class; 

をしかし、注意してください:クラスがちょうどArrayListある - Javaはジェネリックに、実行時に追加の型チェックを実行しません。自分自身を参照してください:それ

ArrayList<Integer> a1 = new ArrayList<>(); 
ArrayList<Double> a2 = new ArrayList<>(); 
System.out.println(a1.getClass() == a2.getClass()); 

同じクラスです。実行時に、ジェネリックは実質的に消えてしまいます

+0

this 'Class > clazz =(クラス>)ArrayList.class;'はコンパイルしないでください。 私は 'super'を使う考えが好きです – nyname00

+0

申し訳ありません、あなたは' super'または 'extends'のダブルキャストが必要です。 –

1

su chのものArrayList<ChildModel>.classとしてこれを解決するためのエレガントな方法はありません。ヤシンで述べたように あなたはこのように、あなたにあなたのコンストラクタを生の型を渡すことができます。

Service<ChildModel, ArrayList<ChildModel>> s1 = 
     new Service<>(ChildModel.class, (Class) ArrayList.class) 

違いをあなたの呼び出しにあなたの例では一方で、ここで我々は、生タイプClassを使用しているということですClass<ArrayList>が使用されています(バグではありません)。

別のオプションは、実際のインスタンスから型を取得するために、次のようになります。

Class<ArrayList<ChildModel>> fromObj = 
     (Class<ArrayList<ChildModel>>) new ArrayList<ChildModel>(0).getClass(); 

これはより冗長ですが、私は、生タイプの上に(両方のケースであなたはコンパイラの警告を取得する)ことを好むだろう

関連する問題