1

これは Android アプリですが、おそらく Java でも同じことが起こります。LevelFactory や Level2Factory などの派生元である LevelFactory 型があります。これらのクラスの配列が必要なので、配列インデックスを指定してレベルをインスタンス化できます。

私はただ Class[] を持っていて、それらをそこに入れ、それらを使用する必要があるときにそれらを LevelFactory にキャストすることができますが、私は何をすべきか疑問に思っていました.

これは明らかに「互換性のない型」のエラーです。

new Class<LevelFactory>[] {Level1Factory.class,Level2Factory.class};

しかし、これも「汎用配列の作成」エラーであることに驚きました。

new Class<? extends LevelFactory>[] {Level1Factory.class,Level2Factory.class};

以下は機能しますが、変数に割り当てられると「未チェックの割り当て」警告が表示されます。

new Class[] {Level1Factory.class,Level2Factory.class};

最後の方法は、私が仕事に取り掛かることができる唯一のオプションです。警告を無視するだけですが、実際に可能であればジェネリックを使用したいと思います。

4

3 に答える 3

5

本「効果的なJava」の項目25「配列よりもリストを好む」を読むことをお勧めします。Joshua Bloch は次のように書いています。

ジェネリック配列の作成が違法なのはなぜですか? タイプセーフではないからです。それが正当である場合、他の点では正しいプログラムでコンパイラによって生成されたキャストは、実行時に ClassCastException で失敗する可能性があります。これは、ジェネリック型システムによって提供される基本的な保証に違反します。

UPD:たぶん、具体的な例があれば、より理解しやすいでしょう。

まず、配列は共変です。つまり、SuperClass[] を SubClass[] にキャストしたり、その逆を行ったりできます。また、AnyConcreteClass[] を Object[] などにキャストすることが合法であることも意味します。

Set<Cat>[] を持つことが可能であると仮定しましょう (しかし、そうではありません)。誰かがこの配列を Object[] にキャストし、そこに Dog インスタンスのセットを追加した場合、Java は配列が Cat インスタンスのセットのみを含むことを保証できなくなります。型の安全性を壊すと、ジェネリックの本質が壊れます。そのため、ジェネリック配列を持つことは違法です。

Set<Cat>[] cats = new Set<Cat>[]; // illegal
Object[] objects = cats;
objects[1] = new Set<Dog>();
cats[1].add(new Cat()); // Oops! TypeCastException

正直言って、この例もEffective Javaから取られました:)

于 2012-07-08T20:33:17.393 に答える
3

2 つの質問:

  1. 本当にアレイが必要ですか? 配列は、ジェネリックではうまく機能しません。したがって、ArrayList<LevelFactory>より良い解決策かもしれません

  2. 特別なタイプ (Level1Factory、Level2Factory) へのダウンキャストが本当に必要ですか? LevelFactory(たとえば)で定義されている共通のスーパー メソッドがある場合は、Level getLevel()それらをダウンキャストする必要はありません。呼び出すだけgetLevel()で、ファクトリから正しい Level インスタンスを取得できます。

これは一般的な落とし穴のように思われるため、別の注意:

new Class<? extends LevelFactory>

これは有効なステートメントではありません (配列であるかどうかは関係ありません)。<? extends T>左側のタイプのみ有効です。作成されたオブジェクトのジェネリック型が T であるか、T から派生できることを定義します。コレクションの場合、これは、T のオブジェクトまたは T から派生したオブジェクトを格納できることを意味するものではありません (とにかく T のコレクションを作成できます)。

  1. List<LevelFactory> list = new ArrayList<LevelFactory>()これは、LevelFactory、Level1Factory、および Level2Factory のオブジェクトを に追加できることを意味しますlist。からオブジェクトを受け取りたい場合list、タイプはLevelFactoryです。

  2. List<? extends LevelFactory> list = new ArrayList<LevelFactory>()LevelFactoryからのオブジェクトを受け取ることができることを意味しますlistlistしかし、の正確なジェネリック型がわからないため、タイプセーフな方法でオブジェクトを追加することはできませんlist。に割り当てることもできるからnew ArrayList<Level1Factory>()ですlist。つまり、オブジェクトは を実装していないため、LevelFactoryオブジェクトを追加することさえできません。listLevel1Factory

一般<? extends Something>に、ほとんどの場合、コレクションは必要ありません。

于 2012-07-08T20:48:10.760 に答える
1

この方法で配列を作成することはできませんが、この方法new SomeClass<Type>[10]でのみ作成できますnew SomeClass[10]ArrayList<SomeClass<Type>>代わりに使用することを検討してください。

于 2012-07-08T20:34:45.180 に答える