다양한 객체를 다루는 메서드 혹은 클래스에 컴파일 시의 타입 체크를 해주는 기능.
public class Box {
private Object item;
void setItem(Object item) {
this.item = item;
}
Object getItem() {
return this.item;
}
}
String, Integer, Double 등 다양한 타입의 item을 담는 Box 클래스를 정의하면 위와 같다.
다양한 타입을 받기 위해서 item을 Object로 선언한다.
/* Without Generic */
Box stringBox = new Box();
String item = "ITEM";
Integer wrongItem = 1;
if (item instanceof String) {
stringBox.setItem(item);
}
String savedItemFromBox = (String) stringBox.getItem();
Box의 인스턴스인 stringBox에 String 타입의 item만 담고 싶을 때, 이를 보장하기 위해서는 item의 타입을 체크해야한다.
타입 체크가 생략될 경우, item을 꺼내어 사용하는 경우 런타임 시 예외가 발생할 수 있다.
또한, item을 꺼낼 때도 타입 캐스팅을 해야하는 번거로움이 존재하고, 캐스팅을 생략하거나 잘못할 경우 런타임 시 예외가 발생할 수도 있다.
public class GenericBox<T> {
private T item;
void setItem(T item) {
this.item = item;
}
T getItem() {
return this.item;
}
}
/* With Generic */
GenericBox<String> genericStringBox = new GenericBox<>();
String strItem = "ITEM";
Integer integerItem = 1;
genericStringBox.setItem(strItem);
// genericStringBox.setItem(integerItem); <- Compile Error
String savedItemFromGenericBox = genericStringBox.getItem();
제네릭을 사용하는 경우에는, item을 Box에 정해진 타입의 객체만 담을 수 있다.
다른 타입의 item을 담는 경우에는 컴파일 시 오류가 발생하기 때문에 런타임 오류를 막을 수 있다.
즉, 타입 안정성을 보장할 수 있다.
또한, item에 대한 타입 캐스팅을 생략할 수 있어 코드가 간결해진다.