자바의 정석을 통해 공부한 내용을 요약하였습니다
지네릭스의 장점
1. 타입 안정성을 제공
2. 타입체크와 형변환을 생략 -> 코드가 간결해짐
class Box {
Object item;
void setItem(Object item) {
this.item = item;
}
Object getItem() {
return item;
}
}
위와 같이 Object 타입을 사용하는 일반 클래스를 지네릭 클래스로 변경하면 다음과 같다.
class Box<T> {
T item;
void setItem(T item) {
this.item = item;
}
T getItem() {
return item;
}
}
'T' 라는 타입변수를 사용하여 지네릭 클래스로 변경하였다.
타입 변수는 상황에 맞게 의미있는 문자를 선택해서 사용하는 것이 좋다.
기존에 Object 타입을 사용함으로써 형변환이 불가피했지만 타입 변수를 사용하여 원하는 타입을 지정하기만 하면 된다.
예를 들어 Box클래스 객체 생성 시 String 타입을 지정해주게 되면 Box클래스는 아래와 같이 정의된 것과 같다.
Box<String> b = new Box<String>();
class Box {
String item;
void setItem(String item) {
this.item = item;
}
String getItem() {
return item;
}
}
지네릭이 도입되기 이전의 코드와 호환을 위해 지네릭 클래스를 예전 방식으로 객체를 생성하는 것을 허용하지만 경고가 발생하게 된다.
지네릭 클래스를 사용할 때는 반드시 타입을 지정해주는 것이 좋다.
Box b = new Box(); // T는 Object로 간주, 경고 발생
Box<String> b = new Box<String>(); // OK
Box<String> b = new Box<>(); // OK, JDK 1.7부터 생성자 타입 생략 가능
Box< T> - 지네릭 클래스
T - 타입 변수 또는 타입 매개변수
Box - 원시 타입(raw type), 일반 클래스
class Box<T>{
static T item; // 에러
static int compare(T t1, T t2) { //에러
....
}
}
class Box<T>{
T[] itemArr; // OK, T타입의 배열을 위한 참조변수
T[] toArray() {
T[] tmpArr = new T[itemArr.length]; // 에러 지네릭 배열 생성 불가
....
return tmpArr;
}
}
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
int size() { return list.size(); }
public String toString() { return list.toString();}
}
Box<Apple> appleBox = new Box<Apple>(); // OK
Box<Grape> grapeBox = new Box<Apple>(); // 에러. 타입 불일치
Box<Fruit> appleBox = new Box<Apple>(); // 에러. 타입 불일치
Box<Apple> appleBox = new FruitBox<Apple>(); // OK, 다형성
FruitBox<Apple> appleBox = new FruitBox<Apple>();
appleBox.add(new Apple());
appleBox.add(new Grape()); // 에러발생
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
fruitBox.add(new Fruit());
fruitBox.add(new Apple()); // OK , Apple은 Fruit의 자손