2013-09-02 2 views
5

이 컬렉션은 (의 일부) 메소드를 복사 할 수 있습니다 :Collections.copy에서 일반 하위 유형 및 와일드 카드가 작동하는 방식은 무엇입니까?

public static <T> void copy(List<? super T> dst, List<? extends T> src) { 
    for (int i = 0; i < src.size(); i++) { 
    dst.set(i, src.get(i)); 
    } 
} 

4 샘플 호출이 있습니다

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four"); 
List<Integer> ints = Arrays.asList(5, 6); 

1. Collections.copy(objs, ints); 
2. Collections.<Object>copy(objs, ints); 
3. Collections.<Number>copy(objs, ints); 
4. Collections.<Integer>copy(objs, ints); 

어떻게 위의 호출의 작품? 그것은 단지 호출 할 때 허용으로

우리는 또한 몇 가지 가능한 서명

1. public static <T> void copy(List<T> dst, List<T> src) 
2. public static <T> void copy(List<T> dst, List<? extends T> src) 
3. public static <T> void copy(List<? super T> dst, List<T> src) 
4. public static <T> void copy(List<? super T> dst, List<? extends T> src) 

의 예는 위의 호출을 위해

과 방법을 선언 할 수

  • 이들의 첫 번째는 너무 제한적이다 목적지와 소스가 정확히 같은 유형입니다. (Understood). 유형 매개 변수는 형식 매개 변수가 마지막 서명이 세 가지 유형 매개 변수 - 즉, 작동

  • 개체 정수

    경우에만 세 번째 서명이 작동

  • 객체 인 경우에만

  • 두 번째 서명 작동 , 숫자 및 정수

제 2, 제 세 번째이자 마지막 서명을 너무 설명해주십시오?

나머지 세 암시 적 형식 매개 변수를 사용하여 통화에 대해 동일하지만, 명시 적 형식 매개 변수가 다릅니다.

위의 진술은 무엇을 의미합니까?

답변

5

각 서명을 하나씩 살펴 보겠습니다. 당신이 첫 번째 인수로 List<Object>를 통과하는대로

1. public static <T> void copy(List<T> dst, List<? extends T> src) 

당신이 명시 적 형식 매개 변수없이이 메소드를 호출하면

는 유형 매개 변수는 Object로 추정됩니다. 그런 다음 List<? extends Object>Integer을 수락 할 수 있습니다. 당신이 List<Integer> List<? extends Number>에 전달할 수 있지만, 당신은 명시 적 형식 인수 Number로 호출 할 경우 제네릭이 불변으로

그러나 같은, List<Object>List<Number>에 대한 사실이 아니다. 당신이 List<T>List<Integer> 2 번째로 인수를 전달하는 것처럼 암시 적 형식 매개 변수에 대한 다시

2. public static <T> void copy(List<? super T> dst, List<T> src) 

, TInteger로 추정됩니다. 그리고 나서 List<Object>List<? super Integer>의 유효한 대체품입니다.

명시 적 형식 인수가 Number 인 메서드를 호출하는 경우 List<Object>을 첫 번째 인수로 전달할 수 있지만 List<Integer>을 두 번째 인수로 전달할 수 없습니다. 위에서 설명한 것과 같은 이유로.

3. public static <T> void copy(List<? super T> dst, List<? extends T> src) 

이제이 메소드 서명은 모든 유형에 적용됩니다. srcT 인스턴스의 프로듀서 인 반면 추정되는 어떤 유형의 매개 변수에 대해 dstT 인스턴스의 소비자이다. 당신이 명시 적 형식 인수 Number로 호출 할 경우, 예를 들어 들어, List<Object>List<? super Number>로 전환 캡처입니다, 마찬가지로 List<Integer>List<? extends Number>로 전환 캡처입니다. 따라서 두 인수는 유효한 대체입니다. 당신이 명시 적으로 제공하지 않는 경우

그래서, 모든 3의 경우, 컴파일러는 제대로 유형 매개 변수를 추론 할 수있다. 하지만 당신은 이유 존재 여기를 4 서명을 사용한다 - 그것은 하한을 사용해야하므로

  • dstT 인스턴스의 소비자이며,
  • srcT 인스턴스의 생산, 그래서 상한을 사용해야합니다.

관련 포스트 :

참조 :

+0

는 하나는 항상 작동 간단 왜 더 복잡한 서명을 선택 "하지만 당신은 여기에 4 서명을 사용한다"? – newacct

+0

@newacct. 이미 명시 적 형식 인수에 대해서는 다른 대안이 작동하지 않는다고 설명했습니다. 그리고 당신은 그 메소드가 명시적인 타입 인자를 갖거나 갖지 않을 것인지 여부를 알지 못합니다. –

+0

명시 적 형식 인수가 * 올바른 * 명시 적 형식 인수가있는 경우 작동합니다. 해당 서명과 인수에 대해 틀린 명시 적 형식 인수를 선택하면 서명의 문제가 아닙니다. – newacct

관련 문제