6

最近、説明できない一般的なキャストの問題に遭遇したときに、一般的なメソッドをリファクタリングしていました。最後に、T 型を完全に使用せずに (自分でインライン化するだけで) 実行できることに気付きましたが、変換が失敗する理由についてはまだ興味があります。この問題を説明するために、この最小限の例を作成しました。

変換が失敗し、回避策が機能する理由を誰かが説明できますか?

public <K, T extends List<K>> void castLists(List<T> list, K kForBinging) {
    Map<Integer, List<T>> map = mapSizeToList(list);
    // Type mismatch: cannot convert from Map<Integer,List<T>> to Map<Integer,List<List<K>>>
    // Map<Integer, List<List<K>>> expandedMap = map;

    // Added after accepting answer, legal assignment:
    Map<Integer, ? extends List<? extends List<K>>> expandedMap = map;

    // Originally proposed 'work around'
    Map<Integer, ?> lessSpecific = map;
    @SuppressWarnings("unchecked")
    Map<Integer, List<List<K>>> canCast = (Map<Integer, List<List<K>>>)lessSpecific;
    // ...
}

public <A> Map<Integer, List<A>> mapSizeToList(List<A> list) {
    Map<Integer, List<A>> map = Maps.newHashMap();
    // ...
    return map;
}
4

1 に答える 1

6

そのようなことを行う前に、ジェネリックとの共分散が必要だと思います。これは Java ではサポートされていないようです

つまり、Java では、Tが のサブタイプである場合List<K>、それが のサブタイプまたはのサブタイプであることを意味しませんこれが、割り当てがエラーになる理由です。List<T>List<List<K>>Map<Integer,List<T>>Map<Integer, List<List<K>>>

テンプレートパラメータがサブクラスとスーパークラスの関係を持っている場合定義されたクラスまったく同じ関係を持つため、共分散によりこれを行うことができます。これにより、この割り当てが可能になります。Scala (他の (関数型プログラミング?) 言語の中でも)共分散とその補数である分散をサポートしています。

于 2012-12-20T10:02:54.493 に答える