Java

와일드 카드, 지네릭 메서드

1space 2025. 6. 26. 07:07

자바의 정석[기초편]으로 공부한 내용을 정리한 글입니다.

 

하나의 참조 변수로 여러 타입의 제네릭 객체를 참조 가능하게 하기 위한 문법

핵심

ArrayList<? extends Product> list = new ArrayList<Tv>(); // OK
ArrayList<Product> list = new ArrayList<Tv>(); // 에러
  • <?>는 와일드 카드라 부르며, "알 수 없는 타입"이라는 의미입니다.
  • <? extends Product>는 Product와 그 자손 타입만 허용합니다.
    • 예: Product, Tv, Audio 등
  • ArrayList<Product> 타입 참조 변수는 ArrayList<Tv>를 받을 수 없습니다.
    • 제네릭은 타입까지 일치해야 하므로 불일치 에러 발생.

세 가지 와일드카드 형태

  1. <? extends T> → T와 그 자손만 허용 (상한 제한)
  2. <? super T> → T와 그 조상만 허용 (하한 제한)
  3. <?> → 제한 없음. 모든 타입 허용 (<? extends Object>와 동일)

와일드카드의 메서드 활용

static Juice makeJuice(FruitBox<? extends Fruit> box) { ... }
  • FruitBox<Fruit>도 되고 FruitBox<Apple>도 됩니다.
  • box.getList()는 Fruit 또는 자손들이므로 Fruit로 처리 가능.
  • 호출 예:
     
makeJuice(new FruitBox<Fruit>());
makeJuice(new FruitBox<Apple>());

즉, Fruit 또는 그 자손 타입의 FruitBox만 허용한다는 의미입니다.

 

제네릭 메서드

static <T> void sort(List<T> list, Comparator<? super T> c)
  • static <T> → 이 메서드 자체가 타입 매개변수 T를 갖는 제네릭 메서드라는 뜻.
  • 클래스에서 선언한 <T>와는 별개임.
  • 즉, 클래스의 제네릭 타입과는 독립적으로 작동함.
  • Comparator<? super T> → T보다 상위 타입도 비교 가능 (예: Integer, Number, Object)

제네릭 메서드와 타입 생략

  • 메서드를 호출할 때마다 타입이 바뀌므로 유연함.
  • 제네릭 메서드 정의:
     
static <T extends Fruit> Juice makeJuice(FruitBox<T> box)
  • 호출:
     
makeJuice(fruitBox);   // FruitBox<Fruit>
makeJuice(appleBox);   // FruitBox<Apple>

 

  • 컴파일러는 fruitBox 또는 appleBox를 보고 타입 T를 유추하므로 <Fruit> 생략 가능.
  • 단, 타입 추론이 불가능할 때는 <Fruit> 생략하면 오류 발생.

 

정리 비교

  • FruitBox<T>는 제네릭 클래스
  • static <T extends Fruit> Juice makeJuice(FruitBox<T> box)는 제네릭 메서드
  • 아래는 와일드카드 사용 예시:
static Juice makeJuice(FruitBox<? extends Fruit> box)

비교 요약:

구분 선언 위치 의미
<T> 클래스나 메서드에 타입 매개변수 선언 직접 타입 지정 필요
<?> 이미 정해진 제네릭 타입의 대입된 타입을 포괄 타입 추론만 가능, 메서드 내에서는 읽기 전용
<? extends T> T와 그 자손만 허용 (읽기 전용)  
<? super T> T와 그 조상만 허용 (쓰기 전용)  
 

'Java' 카테고리의 다른 글

애너테이션  (0) 2025.06.26
열거형(enum)  (0) 2025.06.26
지네릭스 제약네릭스 제약  (0) 2025.06.25
Iterator, HashMap과 지네릭스  (0) 2025.06.25
지네릭 다형성  (0) 2025.06.25