2009-07-09 7 views
3

私はジェネリックスで常に苦労しています。どうしてこのことが狂っているのか分かりません。私は何度か持っている古い問題があります。 ない作業を行いジェネリックスとクラスで苦闘

class Father { 
    ... 
} 

class Child1 extends Father { 
    ... 
} 

class Child2 extends Father { 
    ... 
} 

public class TestClass { 
    private static Class<? extends Father>[] myNiceClasses = new Class<? extends Father>[] { 
     Child1.class, 
     Child2.class 
    } 
} 

Cannot create a generic array of Class<? extends Father> 

Iは

private static Class<Father>[] myNiceClasses = new Class<Father>[] { 

に(不良)アレイ線を変更すると、同じエラーメッセージが表示されるだけでなく、このメッセージが追加された:

Type mismatch: cannot convert from Class<Child1> to Class<Father> 

コンパイラは、このような文句唯一の作業バージョンは次の行です:

private static Class<?>[] myNiceClasses = new Class<?>[] { 

あなたは簡単にキャストすることができないので、この解決策は満足いくものではありません。

私の質問は:どのようにこの問題を解決するには?私の脳の結び目はどこですか?

答えて

8

これは、Javaが汎用アレイの作成をサポートしていないためです。ジェネリックスはコレクションで最も効果的です。したがって、ArrayListを使用して問題を解決することができます。

 ArrayList<Class<? extends Father>> myNiceClasses = new ArrayList<Class<? extends Father>>(); 
     myNiceClasses.add(Child1.class); 
     myNiceClasses.add(Child2.class); 
+0

+1。コレクションではなく配列でジェネリックを使用します。 – seanmonstar

4

を参照してください彼らは型の安全性を保証することはできませんので、一般的な配列を作成することができないということです。ジェネリックでは許されない配列で終わることができます。とにかくそれを行うために私が知っている最もクリーンな方法は次のとおりです。

private static Class<? extends Father>[] myNiceClasses = 
     (Class<? extends Father>[]) new Class<?>[] {}; 
1

ジェネリックと配列は、組み合わせを避けるのが最善です。コンパイラがジェネリックアレイを作成したくないという事実は、Javaジェネリックスが言語に追加されたものであり、時には結合を見ることができるという事実の成果物です。もう1つの例は例外です。それらをジェネリックと組み合わせることはできません。

このような状況では、配列を避けることをお勧めします。代わりに汎用リストを使用してください。

1

これは、タイプ消去と呼ばれるものによるものです。 Javaコンパイラは、コンパイル処理中にすべての汎用情報を消去します。 (これはジェネリックスが言語に遅れて追加されたためで、下位互換性のためにSunがJVMを変更しないことにしました)。

JVM実行時にジェネリック型を知らない場合、そのジェネリック型の配列をインスタンス化することはできません。あなたのケースでは、生の型の配列をインスタンス化するのがベストですClass

このような場合、ジェネリックを完全にサポートするコレクションフレームワークを使用する方がはるかに優れています。

要約すると、ジェネリックと配列は混在しません。

0

また、amit.devが述べたように、リストを使用することもできます。その場合には、myNiceClassesフィールドが一定になるようになっていると仮定すると、あなたはリストを変更することができないことを確認するためにCollections.unmodifiableListを使用することができます。

private static final List<? extends Father> myNiceClasses; 
static { 
    ArrayList<? extends Father> l = new ArrayList<? extends Father>(); 
    l.add(Child1.class); 
    l.add(Child2.class); 
    myNiceClasses = Collections.unmodifiableList(l); 
} 

それはかなり冗長ですが、それゆえ、完全定数とであるという利点を持っています理由を説明しやすい

関連する問題