Producer Extends Consumer Super

PECS 원칙

  • Producer: 데이터를 생산하는 객체
  • Consumer: 데이터를 소비하는 객체

원칙

  • Producer Extends: 데이터를 읽을 때는 extends 와일드카드를 사용 <? extends T>
  • Consumer Super: 데이터를 쓸 때는 super 와일드카드를 사용 <? super T>

  • <? extends T>: T 타입이나 T의 하위 타입만 허용 (읽기 전용)
  • <? super T>: T 타입이나 T의 상위 타입만 허용 (쓰기 가능)

예시

// Producer (읽기)
List<? extends Number> numbers = new ArrayList<>();
Number n = numbers.get(0);  

// Consumer (쓰기)
List<? super Integer> integers = new ArrayList<>();
integers.add(10); 
  • extends: 요소 추가 불가, 읽기만 가능
  • super: 요소 읽을 때 Object 타입으로만 가능

왜 extends에서 쓰기는 불가능한가에 대해 더 살펴보겠다

List<? extends Number> numbers = new ArrayList<>();

이 경우에 numbers 리스트는 Number의 어떤 하위 타입이든 포함할 수 있따. <? extends Number> 이므로.

근데? 컴파일러 입장에선 정확히 어떤 하위 타입인지 모른다. Integer인지 Double인지 ?

타입을 모르니 numbers.add(new Integer(10))을 허용하면

리스트가 ArrayList<Double>일 경우 타입 안전성이 깨진다.

이런 이유로 쓰기가 불가능한 것이다.

List<? super Integer> integers = new ArrayList<>();

이 경우를 살펴보겠디.

integers 리스트는 Integer의 어떤 상위 타입이든 될 수 있다.

뭐 Number일 수도, Object일 수도 있다.

컴파일러는 정확한 타입을 모르니 가장 상위 타입인 Object로 읽을 수 있다.

근데 왜 쓰기가 가능할까? 당연한 것이다. Integer 타입이 Number든, Object든 상위 타입에 안전하게 들어갈 수 있으니 쓰기가 가능하다.