以下が機能しないのはなぜですか?
Vector<? extends SomeClass> v = new Vector<SomeClass>();
SomeClass e = new SomeClass();
v.add(e);
次のようなコンパイル エラーが発生します。
Vector 型のメソッド add(capture#1-of ? extends SomeClass) は、引数 (SomeClass) には適用されません。
Collections with generic wildcards which extend from a type do not allow you to add to that Collection
.
As the compiler does not know exactly what type of SomeClass
you are attempting to add, it doesn't allow it. The exception to this is a null
object which can represent any type of Object
.
To answer your comment: Although you cannot add to the Collection
, it cannot be described as read only as it is still possible to remove Objects
.
To allow addition of Objects
, you would need to use a known type:
Vector<SomeClass> v = new Vector<SomeClass>();
基本的に問題は、v
あなたVector<? extends SomeClass>
が言うように、それがコレクションSomeClass
またはそのサブクラスの1つであると宣言することです。new Vector<SomeClass>()
コンパイラは、同じ行で割り当てが行われたとしても、コンテナーが実際に保持している特定の型について推測することはできません。v
として作成された可能性があるとコンパイラが認識している限り、 new Vector<SubClassOfSomeClass>()
. そのため、コレクションにインスタンス (またはその他のもの)を入れる ことを拒否しています。SomeClass
ただし、そこから要素を取得できます。SomeClass
要素をコレクションに配置できるようにしたい場合は、 v
asを宣言しVector<? super SomeClass>
ます。これにより、それが のコンテナーSomeClass
またはそのスーパークラスの 1 つであると言えます。コンパイラは、SomeClass
インスタンスがそのようなコレクションに確実に収まることを認識します。ただし、コンパイラはコレクション内の要素のタイプについて何も知らないため、そのコレクションから要素を取得する
ことはできません(ただし、それが のスーパークラスであることを除きます)。の定義によれば、単に のコレクションである可能性もあります。SomeClass
SomeClass
v
Object
これは、要するにput/get 原則と呼ばれ、このような他の投稿でも詳しく説明されています。
これについては、こちらで説明しています。そのように宣言されたリストは実質的に読み取り専用リストですが、通常のリストよりも柔軟ですList<AbstractClass>
。
抽象クラスをテンプレートとして使用する場合は、次のようにそのまま使用しますList<SomeClass> list
。
Java 言語仕様を読むことを検討してください。ジェネリックロジックに関する多くの情報があります。
問題の説明に問題はないはずです。次のコードのように問題を理解しました。
import java.util.*;
class Test
{
int x;
}
public class Demo
{
public static void main(String args[])
{
Vector<Test> vect = new Vector<Test>();
Test t1 = new Test();
Test t2 = new Test();
t1.x = 10;
t2.x = 20;
vect.add(t1);
vect.add(t2);
for(Test t : vect)
{
System.out.println(t.x);
}
}
}
Vector Play Withでこの種のギミックを読みました。