원문링크

제한없는 와일드카드 Unbounded Wildcards

제한없는 와일드카드 타입은 와일드카드 문자(‘?’)만 사용한것이다. 예를 들면 List<?>와 같다. List<?>의 ?는 List의 ‘알수없는 타입(unkown type)‘이라고 부른다. 아래 두개의 시나리오는 제한없는 와일드카드가 유용한 접근법이다.
The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:

  • Object 클래스에서 제공하는 기능(메서드)을 사용하도록 메서드를 구현할 때.
    If you are writing a method that can be implemented using functionality provided in the Object class.`
  • 코드가 generic 클래스에서 메서드가 타입매개변수에 의존적이지 않게 작성하고 싶을 때.(예 List.size나 List.clear). 사실, Class<T> 클래스는 범위없는 와일드카드를 자주 사용한다.(Class<T>의 메서드가 T에 의존적으로 동작하지 않게 만들기 위해)
    When the code is using methods in the generic class that don’t depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class do not depend on T.

printList 메서드를 살펴보자.
Consider the following method, printList:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " "); // elem.toString() 자동으로 호출됨.
    System.out.println();
}

printList는 List가 가진 객체가 어떤 타입이든간에 상관없이 print하고 싶어한다. 하지만 List 객체는 Object 타입의 객체만 출력할 수 있다. (참조:제네릭스, 상속, 서브타입) List<Object>는 List<Integer>, List<String>, List<Double>을 출력할 수 없다. 왜냐하면 List<Object> 타입의 stub type(스텁타입 용어 아시는분 공유 부탁요 ㅠㅠ)이 아니다. 아래는 List<?>를 사용해서 generic 메서드인 printList를 작성한 예이다..
The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print List, List, List, and so on, because they are not subtypes of List. To write a generic printList method, use List<?>:

(역자 추가 - 위의 예가 설명하는 코드 - 컴파일 에러 발생)

List<Integer> integerList = Arrays.asList(1,2);
printList(integerList);   // 컴파일 에러
public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

아무 타입을 A로 지칭했을때, List<?>의 서브타입은 List<A>이 성립이 되기 때문에, printList 메서드가 모든 타입을 대상으로 print할 수 있다.
Because for any concrete type A, List is a subtype of List<?>, you can use printList to print a list of any type:

List<Integer> li = Arrays.asList(1, 2, 3);
List<String>  ls = Arrays.asList("one", "two", "three");
printList(li);
printList(ls);

참고: Arrays.asList 메서드는 범위없는 와일드카드를 사용해서 구현되었다. Arrays.asList라는 static 팩토리 메서드는 배열을 구체화하여 변경하고(요소들의 공통 타입을 타입추론) 고정된 사이즈의 리스트를 반환한다.
Note: The Arrays.asList method is used in examples throughout this lesson. This static factory method converts the specified array and returns a fixed-size list.

(중요!)List와 List<?>과 다르다. List에 Object 타입이나 Object의 서브타입을 insert할 수 있다. 하지만 List<?>에는 null만 insert할 수 있다.(하고자하는 말이 무언지 이해가 안된다;;;) 와일드카드 사용 섹션은은 상황별 어떤 와일드카드를 사용할지 결정에 대한 가이드라인을 제공한다.
It’s important to note that List and List<?> are not the same. You can insert an Object, or any subtype of Object, into a List. But you can only insert null into a List<?>. The Guidelines for Wildcard Use section has more information on how to determine what kind of wildcard, if any, should be used in a given situation.

comments powered by Disqus