신발 하나가 있고 그 신발을 여러가지 색으로 만들고 싶을 경우, 신발의 기본형태는 정해져있고 거기에 색만 빨간색으로 할것인가 파란색으로 할것인가 결정하면 됩니다.
여기서 빨간색 파란색은 자바에서 자료형을 의미하고
빨간색 파란색을 칠할 수 있는 신발 자체를 제네릭이라고 할 수 있습니다.
제네릭이란 → 자료형을 결정 짓지 않고 틀만 정해놓는 클래스 정의
C++에서의 템플릿과 같다고 생각하자'
어떠한 인스턴스라도 넣을 수 있는 박스 클래스가 있다고 가정하면
class Apple {
public String toString() {
return "I am an apple.";
}
}
class Orange {
public String toString() {
return "I am an orange.";
}
}
class Box {
private Object ob;
public void set(Object o) {
ob = o;
}
public Object get() {
return ob;
}
}
위와 같은 클래스에서 반환을 Object 클래스로 해주기 때문에
제네릭 이전에는 (Apple),(Orange) 같이 명시적 형 변환을 일일이 해주어야 했습니다.
이는 컴파일러의 오류 발견 가능성을 낮추는 결과로 이어집니다.
(코드의 안정성이 낮아짐)
제네릭 이전, Object를 통해 제네릭을 비슷하게 구현했을 경우 발생할 수 있는 문제점들
무조건 형 변환을 해 주어야 한다.
컴파일 과정에서 오류를 발견하지 못할 수 있다.
예외 처리에도 안걸려서 프로그램은 잘 실행되는데 예상치 못한 에러에 발목을 잡힐 수 있다.
Object로 구현할 때는 T 위치가 Object형으로 정해져 있었는데, 제네릭을 활용하면서 Object 같은 특정 클래스로 정해두지 않고 미지의 T로 공간을 비워둘 수 있습니다.
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
타입 매개변수 → Box< T >에서 T
타입 인자 → Box< Apple >에서 Apple
매개변수화 타입 → Box< Apple >타입 매개변수 T에 타입 인자(Apple, Orange 등)이 전달되어 새로운 타입이 생성될 경우 컴파일러는 해당 타입을 각각 다른 클래스로 보게 됩니다.
Box 과 Box는 다른 타입으로 간주
인스턴스 생성
Box<Apple> aBox = new Box<Apple>();
T를 Apple로 다 치환하여 인스턴스를 생성합니다.
이경우 Apple 또는 Apple을 상속하는 하위 클래스의 인스턴스를 저장 가능합니다.
제네릭을 통해 선언할 때는 자유롭지만 선언 이후에는 T에 넣어둔 타입 인자에 맞게 매개변수를 전달하고, 반환값을 받아와야 하기에 컴파일러 단에서 에러를 잡을 수 있게 됩니다.
Box<Apple> aBox = new Box<Apple>();
//컴파일 에러
aBox.set("Apple");
aBox.set(new Apple());
//컴파일 에러
Orange o = aBox.get();
Apple a = aBox.get();