이 글은 남궁성님의 자바의 정석 3/e를 기반으로 공부한 내용을 정리한 글입니다.
class Box {
Object item;
void setItem(Object item){
this.item = item;
}
Object getItem(){
return item;
}
}
class Box<T> { // 제네릭 타입 T를 선언
T item;
void setItem(T item). { this.item = item; }
T getItem() { return item; }
}
기존에는 다양한 종류의 타입을 다루는 메서드의 매개변수나 리턴타입으로 Object타입의 참조변수를 많이 사용했지만, 이젠 Object타입 대신 원하는 타입을 지정하면 된다.
Box<Apple> appleBox = new Box<>(); // OK. Apple객체만 저장가능
Box<Grape> grapeBox = new Box<>(); // OK. Grape 객체만 저장가능
class Box<T> {
static T item; // 에러
static int compare(T t1, T t2){ ... } // 에러
}
//static 멤버에 T를 사용하면
//Box<Apple>.item과 Box<Grape>.item이 다르면 안되기 때문
class Box<T> {
T[] itemArr; // Ok. T타입의 배열을 위한 참조변수
T[] toArray() {
T[] tmpArr = new T[itemArr.length];
// 에러. 제네릭 배열 생성 불가
...
return tmpArr;
}
}
// 제네릭 타입의 인스턴스를 생성했을 때
// 컴파일 시 T가 어떤 타입인지 알 수 없기 때문
class FruitBox<T extends Fruit> {
ArrayList<T> list = new ArrayList<T>();
}
interface Eatable {}
class FruitBox<T extends Eatable> { ... }
// 자손이면서 인터페이스도 구현해야 한다면 '&'기호 사용
class FruitBox<T extends Fruit & Eatable> { ... }
<? extends T> 와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T> 와일드 카드의 하한 제한. T와 그 조상들만 가능
<?> 제한 없음. 모든 타입이 가능. <? extends Object>와 동일