14

コンパイルしようとするのはなぜですか

public class GenericsFail {
    public static void main(String[] args) {
        accept(new HashMap<String, List<String>>());
    }

    public static void accept(Map<String, List<?>> multiMap) {}
}

エラーを与える

GenericsFail.java:7: error: method accept in class GenericsFail cannot be applied to given types;
                accept(new HashMap<String, List<String>>());
                ^
  required: Map<String,List<?>>
  found: HashMap<String,List<String>>
  reason: actual argument HashMap<String,List<String>> cannot be converted to Map<String,List<?>> by method invocation conversion

ワイルドカードは、 内にネストされていない場合にのみ許可されListます。

4

3 に答える 3

13

その理由は、?inList<?>は「なんでも」である可能性がありますが、各エントリの「なんでも」は異なるからです。Mapつまり、List<String>あるエントリでa を受け入れ、List<Integer>別のエントリで a を受け入れます。

ただし、すべてのエントリで同じタイプのを渡しているMapため、タイプは同じ方法または同じ自由度でバインドされていません。List

「修正」は、タイプを特定のタイプにロックすることですが、それでも「何でも」です-メソッドを入力することにより、すべてのエントリで同じ「何でも*」です:

public static <T> void accept(Map<String, List<T>> multiMap) // complies

または、メソッドが実際にどの型を知る必要がない場合は、ワイルドカードを使用して型をラップします。

public static void accept(Map<String, ? extends List<?>> multiMap) // compiles

この最後のバージョンが機能するのは、リストの型がワイルドカードであるにもかかわらず、呼び出されたときに不明ではあるが一貫した型に固定されるためです。


型付けされたバージョンの方が読みやすく (およびコードも) 読みやすいと思います。型は、後でメソッドが型を知る必要があると判断した場合に使用するためにあります。

于 2012-10-24T19:48:42.900 に答える
4

より一般的になるために

void accept(Map<String, ? extends List<?>> multiMap)
于 2012-10-24T20:32:09.963 に答える
2

コンパイラーがこのパラメーターを受け入れられない理由の簡単な例を次に示します。

    public static void main(String[] args) {
        //if this would be accepted here ...
        accept(new HashMap<String, List<String>>());
    }

    public static void accept(Map<String, List<?>> multiMap) {
        //this is valid considering the type of multiMap parameter,
        //but would not work with the actual passed parameter.
        multiMap.put("test", new ArrayList<Integer>());
    }
于 2012-10-24T20:09:45.237 に答える