다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입체크(compile-time type check)를 해주는 기능
타입 안정성 제공
타입 체크와 형변환을 생략할 수 있으므로 코드 간결
class Box<T> { // 지네릭 타입 T를 선언
T item;
void setItem(T item){ this.item=item; };
T getItem(){ return item; }
}
Box<String> box = new Box<String> // 타입 T 대신 String으로 지정
box.setItem(123) String // 에러. String 이외의 타입은 지정 불가
box.setItem("123") // String 타입이므로 가능
String item = box.getItem(); // 형변환이 필요없음
지네릭 타입 호출 : 타입 매개변수에 타입을 지정하는 것
매개변수화된 타입(대입된 타입) : 지정된 타입
지네릭 타입이 다른 것 만으로 오버로딩 성립 X
static 멤버에 타입 변수 T 사용 X (대입된 타입의 종류와 관계 없이 동일한 것이어야 함)
class Box<T> {
static T item;
static int compare(T t1, T t2) { ... } // 에러
지네릭 타입의 배열 생성 X (new 연산자 때문 - 컴파일 시점에 타입 T가 뭔지 정확히 알아야 함)
class Box<T> {
T[] itemArr; // T타입의 배열을 위한 참조변수
T() toArray() {
T[] tmpArr = new T[itemArr.length]; // 지네릭 배열 생성 불가
...
return tmpArr;
}
}
제네릭 타입에 extends 사용 → 특정 타입의 자손들만 대입할 수 있게 제한
clss FruitBox<T extends Fruit> { // Fruit의 자손만 타입으로 지정 가능
ArrayList<T> list = new ArrayList<T>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
FruitBox<Toy> toyBox = new FruitBox<Toy>(); // 에러, Toy는 Fruit의 자손이 아님
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
fruitBox.add(new Apple()); // Apple이 Fruit의 자손
fruitBox.add(new Grape()); // Grape가 Fruit의 자손
}
인터페이스 구현
interface Eatable {}
class FruitBox<T extends Eatable> {...}