다양한 타입의 객체를 다루는 메서드나 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. 제네릭 타입은 클래스와 메서드에 선언할 수 있다.
객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성이 높아지고, 형변환의 번거러움이 줄어든다.
class Apple{
}
//사과(Apple)만 저장할 수 있는 클래스
class Goods1{
private Apple apple = new Apple();
public Apple get() {
return apple;
}
public void set(Apple apple){
this.apple = apple;
}
}
//사과를 저정(set)하고 가져오기(get)
Goods1 goods1 = new Goods1();
goods1.set(new Apple());
Apple apple = goods1.get();
class Pencil{
}
//연필(Pencil)만 저장할 수 있는 클래스
class Goods2{
private Pencil pencil = new Pencil();
public Pencil get() {
return pencil;
}
public void set(Pencil pencil){
this.pencil = pencil;
}
}
//연필을 저정(set)하고 가져오기(get)
Goods2 goods2 = new Goods2();
goods2.set(new Pencil());
Pencil pencil = goods2.get();
사과와 연필을 저장하고 관리하기 위해 각각의 기능을 수행하는 클래스 2 가지를 만든 것
-> 비효율적이다.
class Apple{}
class Pencil{}
class Goods{
private Object object = new Object();
public Object get(){
return object;
}
public void set(Object object){
this.object = object;
}
}
Goods goods1 = new Goods();
goods1.set(new Apple()); //Apple 저장
Apple apple = (Apple)goods1.get(); // Object ->Apple
Goods goods2 = new Goods();
goods2.set(new Pencil()); //Pencil 저장
Pencil pencil = (Pencil)good2.get(); Object -> Pencil
->데이터를 저장할때는 상관이 없지만 저장된 데이터를 각각의 타입으로 꺼내오기 위해서는 저장된 형태로 캐스팅 을 해줘야한다. 필드가 Object 타입이기 때문에 get()메서드로 가져오는 타입 또한 항상 Object 타입이다(Object=최상위 클래스).
프로그래머의 실수로 잘못 캐스팅 했을때도 ClassCastException은 실행 예외이기 때문에 문법 오류는 발생하지 않는다.
// 일반적인 클래스
class Box {
Object item;
void setItem(Object item) {this.item = item;}
Object getItem() {return item;}
}
// 제네릭 클래스
class Box<T> {
T item;
void setItem(T item) {this.item = item;}
T getItem() {return item;}
}