web-dev-qa-db-ja.com

ジェネリックと疑問符

汎用リストを使用したいのですが、初期化メソッドはListしか返しません。次のコードはうまく機能します:

_List tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
_

Javaは、私がraw型を使用していると非難しているので、リストをパラメーター化する必要があります。そこで、このリストをパラメータ化する疑問符を追加しました。

_List<?> tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
_

問題は次のとおりです。add(..)メソッドが機能しなくなりました。
aMethodToInitializeTheColumnList()myコードに実装されていないため、リストにStringsのみが含まれていることを保証できません。

私の間違いは何ですか?

ありがとう!

16
guerda

Genericsチュートリアルから。おかげで マイケルの答え

ただし、任意のオブジェクトを追加するのは安全ではありません。

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error

Cの要素タイプが何を表すのかわからないため、オブジェクトを追加することはできません。 add()メソッドは、コレクションの要素タイプであるタイプEの引数を取ります。実際の型パラメーターが?の場合、不明な型を表します。 追加するために渡すパラメータは、この不明なタイプのサブタイプである必要があります。タイプがわからないため、何も渡すことができません。 in。唯一の例外はnullで、これはすべてのタイプのメンバーです。

28
guerda

おそらくList<String>を使用することをお勧めします。これは、ジェネリックスの使用を目的とした方法です。つまり、コレクションに含まれるオブジェクトの種類に関する情報を追加します。混合タイプを含むリストを実際に作成する場合(通常は設計が悪いことを示しています)、List<Object>を使用します。

ワイルドカードの使用の詳細については、 ジェネリックチュートリアル を参照してください。ただし、実際には、独自のジェネリッククラス、またはジェネリックパラメーターを使用してメソッドを定義する場合にのみ関係します。

18

<?>を使用する場合は、パラメータ化されたタイプをどこにも使用しないことを意味します。特定のタイプ(あなたの場合はList<String>のようです)または非常に一般的なList<Object>に移動します

16
Romain

この場合の別のオプションは、リストを次のように宣言することです。

_List<? super String>
_

このモデルなので正確にあなたがそれについて知っていること。型の境界が正確にわからないと言いますが、2行目からは、文字列を含めることができなければならないと考えるのが妥当です。

これはコンパイルされ、私の考えでは、実際にリストに何が入るかについての不確実性をエンコードするため、_List<Object>_よりも少し優れています。基本的には、add Stringsしかできませんが、get()を呼び出すと、返される要素は何でもかまいません(Javaはこれを正しく推測します) Object)と入力します。

実際には、これと_List<Object>_の唯一の違いは、後者ではtmpColumnList.add(3)tmpColumnList.add(new Thread())などが許可されることです。実用性だけでなくセマンティクスも非常に好まれます。 。

8
Andrzej Doyle

List<?>は、リストが入力されている(または入力される可能性がある)が、タイプが不明であることを意味します**。したがって、タイプの外にいる場合は、何かを追加するのは間違っている可能性があります**。不明なため、警告が表示されます。

List<Object>を使用できます。これは、任意のタイプを含むことができるリストを意味します。

2
KLE