본문 바로가기

Java

Generics

  • 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크(compile-time type check)를 해주는 기능
    • 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.

지네릭 클래스

class Box<T> {  // 지네릭 타입 T를 선언
	T item;
    
    void setItem(T item) { this.item = item; }
    T getItem() { return item; }
}
  • T 는 타입 변수(type variable)
  • Box는 원시 타입(raw type)

제한된 지네릭 클래스

class FruitBox<T extends Fruit> {   // Fruit의 자손만 타입으로 지정가능
	ArrayList<T> list = new ArrayList<T>();
    ...
}
class FruitBox<T extends Fruit & Eatable> { ... }   // Fruit의 자손이면 Eatable 인터페이스 구현

와일드 카드

  • 지네릭 클래스가 다른 메서드의 변수로 쓰일 때
  • runtime에 지네릭 클래스의 타입이 정해진다면?
<? extends T>   와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T>     와일드 카드의 하한 제한. T와 그 조상들만 가능
<?>             제한 없음. 모든 타입이 가능. <? extends Object>와 동일
static <T> void sort(List<T> list, Comparator<? super T> c)
  • Comparator에 하한을 제한하는 와일드 카드가 쓰인 이유?
    • 만약 Apple 타입으로 지정되어 Apple의 compare 메서드를 구현했을 때, Grape 타입으로는 정렬이 불가능함.

지네릭 메서드

  • 지네릭 메서드는 메서드의 선언부에 지네릭 타입이 선언된 메서드이다.
static Juice makeJuice(FruitBox<? extends Fruit> box) { ... }

// 위 메서드를 지네릭 메서드로 바꾸면 다음과 같다.

static <T extends Fruit> Juice makeJuice(FruitBox<T> box) { ... }
// 위 sort 메서드를 다음과 같이 작성할 수 있다.
public static <T extends Comparable<? super T>> void sort<List<T> list)
  • 사용 예시
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
...
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));   // 대입된 타입을 생략할 수도 있다.