2009-05-16 5 views
6

다음과 같은 유형을 안전하게 구현할 수있는 방법이 있습니까?Java Generics가 Map <String,?을 (를) 사용하고 있습니다. extend List <String>>

public void myMethod(Map<String, ? extends List<String>> map) 
{ 
    map.put("foo", Collections.singletonList("bar"); 
} 

위의 구현은 작동하지 않습니다. map.put() 메서드를 올바르게 컴파일하려면 Map<String, ? super List<String>>이 필요합니다. 그러나 myMethod는 이런 방식으로 List의 하위 유형을 허용하지 않습니다. 그래서 대신 Map<String, ? extends List<String>>을 사용해야합니다. 유형 안전 방식으로이 문제를 어떻게 해결할 수 있습니까?

답변

20
public void myMethod(Map<String, List<String>> map) { 
    map.put("foo", Collections.singletonList("bar")); 
} 
실제의 형태가 List의 구현이 될 수 있기 때문에 당신은 ? extends ListMapCollections.singletonList()List (리턴 타입을 넣을 수 없습니다

. 예를 들어,이 하지 일반적인 넣어 안전 ListList 이후 Map<String,LinkedList>LinkedList하지 않을 수 있습니다로. 그러나, 우리는 쉽게 <String,List>MapLinkedList를 넣을 수 있습니다.

을 내가 승을 생각한다 당신의 제네릭을 생각 해보세요. 비 제너릭 클래스에 ? extends을 사용할 필요는 없습니다. 예를 들어, List<Object>Object을 유지하고, ? extends은 개체를 추가 할 필요가 없습니다. List<List<Foo>>은 [일반 클래스는 매개 변수를 기반으로 상속하지 않습니다.] 개체가 아닌 개의 개체 만 사용합니다. 이것은 ? extends이 나오는 곳입니다. List<Foo>List<FooSubclass>을 모두 List에 추가하려면 형식은 List<List<? extends Foo>>이어야합니다.

+2

+1 좋은 설명을 위해 (이제 제네릭이 표시됨 : P). –

+0

죄송합니다. 나는 SOF가 어쨌든 텍스트를 필터하기 때문에 각진 브래킷을 고쳤다 고 생각한다. 오 잘 ... – KitsuneYMG

6

Map<String, List<String>하지 않습니까? 거기에 와일드 카드가 있어야하는 특별한 이유가 있습니까?

0

누군가가 너에게 Map<String, ArrayList<String>>을 전달한 경우를 상상해보십시오. 넣는 값은 Collections.singletonList의 결과입니다. 이 아니고이 아닌 ArrayList입니다.

당신은지도에서 목록의 하위 유형을 수용하고 자신의 가능성 호환되지 않는, 하위 유형을 추가 할 수 있기를 기대 할 수 없다.

4

컬렉션과 제네릭을 함께 사용하면 매우 간단한 원리가 있습니다.

컬렉션에서 값만 가져올 때 와일드 카드를 사용하고 컬렉션에 값만 넣을 때 "슈퍼"와일드 카드를 사용하고 사용하지 마십시오 모든 와일드 카드는 get 및 put을 모두 원할 때 사용됩니다.

이 원리에 따르면 처음 예제는 유효하지 않습니다.

관련 문제