1

私はJavaでMongoDBインターフェースを書いていて、最近このコードの障害に遭遇しました。

ドキュメントを挿入する呼び出しがあります。

insertMongoDocument(String testName, Map<String, Object> input)

そして、対応する単体テストがあります:

Writer.insertMongoDocument("TestName", testMap);

テストマップは次の形式です

protected static Map<String, List<?>> testMap;

なぜこれが違法な議論になるのですか?は ではありMap<String, List<?>>ませんMap<String, Object>か?

4

3 に答える 3

4

Java では、型は宣言どおりに正確に一致する必要があります。それが与えられる

insertMongoDocument(String testName, Map<String, Object> input)

あなたはそれを呼び出すことはできません

Map<String, List<?>> map;
insertMongoDocument("foo", map);

Map<String, List<?>>のインスタンスであるように見えますがMap<String, Object>、そうではありません。

これは、基本的な継承に従っていないように見えるジェネリックの別のケースです。つまり、のインスタンスでList<SubClass>はありませんList<SuperClass>

それが本当なら、次のバグが発生します。

List<Integer> listI = new ArrayList<Integer>();
List<Number> listN = listI; // compile error, but let's assume OK
listN.add(1.2); // Adding a Double (which is a Number) to a list of Integer - oops!
Integer i = listI.get(0); // BOOM... ClassCastException!

この線

List<Number> listN = listI;

明らかな理由で許可されていません.これは基本的にあなたが見ているものです.クラスのようにジェネリック型をキャストすることはできません.

于 2013-09-25T14:33:14.047 に答える
2

次の署名を使用する必要があります

insertMongoDocument(String testName, Map<String, ? extends Object> input)

これは、Java がパラメトリック型を関連付けることができないためです。知っているルールのみを適用しようとします。元の署名でObjectは、 の 2 番目の型パラメーターを受け入れることができることがわかっているため、正確に一致しないMapものを見つけてエラーを返します。完全一致ではなく、適用可能なタイプのセットを指定するには、and演算子を使用する必要があります。List<?>extendsuper

唯一無二の Jon Skeet が、このトピックについて優れた説明をしています: What is difference between <? スーパーE>と<? E> を拡張しますか?

于 2013-09-25T14:34:00.630 に答える
0

それが合法である場合、それを insertMongoDocument のようなメソッドに渡して、input.put("", new Anything())型の安全性を破壊する呼び出しを試みる可能性があるためです。

ここで署名に使用できる最も一般的なタイプはinsertMongoDocument( String s, Map< String, ? super List< ? > > ).

于 2013-09-25T14:34:10.033 に答える