2

Java チュートリアル ( http://docs.oracle.com/javase/tutorial/extra/generics/fineprint.html ) で、次のように表示されました。

// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;

// Run-time error: ClassCastException.
String s = lsa[1].get(0);
If arrays of parameterized type were allowed, the previous example
would compile without any unchecked warnings, and yet fail at run-time


// OK, array of unbounded wildcard type.
List<?>[] lsa = new List<?>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Correct.
oa[1] = li;
// Run time error, but cast is explicit.
String s = (String) lsa[1].get(0);

彼らは、切り替えれば大丈夫だと説明しList<String>[] lsa = new List<String>[10];まし List<?>[] lsa = new List<?>[10];たが、アップキャストする必要があります。

私の教授はこれについて次のように尋ねました:「なぜ後者はコンパイルするのですか?」

「引数が ? の場合、意味は、配列内のすべてのセルに ArrayList を含めることができるということです。ジェネリック クラスの型に関する仮定がないため、前の例外は発生しません。」

ワイルドカードが機能し、前のものは機能しないということは、私にはまだ本当に意味がありません。ワイルドカードの例でアップキャストを強制する必要がある場合、最初の例でもそれを実行できないのはなぜでしょうか?

誰かが私のためにこれを片付けてくれれば幸いです。

4

3 に答える 3

1

ワイルドカードの 1 つはキャストを強制するため、実際のクラスを知るのはあなた次第です。

最初のケース (可能であれば) では、誤った安心感が得られ、警告が表示されません。これは、ジェネリックの全体的なポイントは、常に何かをキャストしなくても作業できるようにすることだからです。

于 2013-10-18T19:19:39.327 に答える
0

ジェネリックは、特定の型を提供する場合に備えて型安全になるように設計されています。しかし、型の消去により、ジェネリック リストに正確に格納できる型の情報が失われます。?これは、タイプとして提供する場合と同じ効果があります。実行時に、型が常に正しいかどうかわからないため、コンパイラは文句を言います。

両方のバリエーションのデータは同じですが、一方のバリエーションはコンパイルされ、もう一方はコンパイルされません。これは、ワイルドカードを指定すると、基本的にスイッチのようにコンパイラの型安全性をオフにし、自分で気にすることを伝えるためです。失敗した場合、それはあなた自身の責任であり、コンパイラのせいではありません。:)

于 2013-10-18T19:37:27.633 に答える
0

最初のものが許可されない実際の理由は、Java の型システムが適切でないためです。

仕様によると、Sis-a のT場合はS[]is-aT[]です。残念ながら、このルールは型の問題を引き起こします:

void unsoundness( Animal[] aanl ) {
    // causes a runtime type check that the element types are compatible
    aanl[ 0 ] = new Animal(); 
}

Dog[] adog = new Dog[ 1 ];
unsoundness( adog );

ジェネリックと型消去では、そのランタイム型チェックは正しい判断を下すことができません。

void unsoundness( List< ? extends Animal >[] alstr ) {
    alstr[ 0 ] = new ArrayList< Animal >();
}

List< Dog >[] alobj = new List< Dog >[ 1 ]; // fictitious
unsoundness( alobj );
于 2013-10-18T20:12:13.943 に答える