개요
•
자바 1.5 버전부터 도입됨 (@ 애노테이션, enum 등과 같이)
•
소프트웨어적 해결이 아닌, 문법을 도입한 것
•
컴파일 시 타입 체크를 해주는 기능을 제공 > 즉, 타입이 이미 결정되어짐
•
예시
// 지네릭 사용 전
class Apple{
@Override
public String toString() {
return "나는 사과입니다.";
}
}
class Orange{
@Override
public String toString() {
return "나는 오렌지 입니다.";
}
}
class Box{
private Object obj;
public void set(Object obj) {
this.obj = obj;
}
public Object get() {
return obj;
}
}
////////////////
Box aBox = new Box();
Box oBox = new Box();
aBox.set(new Apple());
oBox.set(new Orange());
// 문제점 1.
// 형변환 과정이 반복되면 프로그래머의 실수가 컴파일 과정에서 발견되지 않을 가능성이 높아진다.
Apple ap = (Apple) aBox.get(); //형변환 과정이 반드시 필요함
Orange og = (Orange) oBox.get();////형변환 과정이 반드시 필요함
System.out.println(ap);
System.out.println(og);
}
}
Java
복사
// 지네릭 사용 전 문제점 2.
// 실수가 프로그램 실행 과정에서도 발견되지 않을 수 있다.
public static void main(String[] args) {
Box aBox = new Box();
Box oBox = new Box();
// 다음 두 문장은 프로그래머의 실수이다!
aBox.set("Apple");
oBox.set("Orange");
System.out.println(aBox.get());
System.out.println(oBox.get());
}
Java
복사
제네릭 기반의 클래스 정의 > 인스턴스 생성
1.
인스턴스 생성 시 결정되는 자료형의 정보를 T로 대체
2.
T를 Apple, Orange로 결정하여 인스턴스 생성
// 제네릭 이후의 코드
public static void main(String[] args) {
Box<Apple> aBox = new Box<Apple>(); // T를 Apple로 결정
Box<Orange> oBox = new Box<Orange>(); // T를 Orange로 결정
aBox.set(new Apple()); // 사과를 상자에 담는다.
oBox.set(new Orange()); // 오렌지를 상자에 담는다.
Apple ap = aBox.get(); // 사과를 꺼내는데 형 변환 하지 않는다.
Orange og = oBox.get(); // 오렌지를 꺼내는데 형 변환 하지 않는다.
System.out.println(ap);
System.out.println(og);
}
Java
복사
제네릭스의 용어
•
Box<T> : 제네릭 클래스. ‘T의 Box’ 또는 ‘T Box’라고 읽음
•
T : 타입 변수 또는 타입 매개변수 (T는 타입 문자)
•
Box : 원시 타입(raw type), 일반 클래스일 때 타입
제네릭 클래스의 제한
•
타입 인자 제한
class Box<T extends Number>{...}
Java
복사
•
인스턴스 생성 시 타입 인자로 Number or 이를 상속한 클래스만 올 수 있음
•
타입 인자 제한의 효과
◦
number 안에 intValue 함수를 기본적으로 내부에서 사용하기를 원함 > 타입 제한을 미리 걸어버리는 것
제네릭 메소드
•
클래스 전부가 아닌 메소드 하나에 대해 제네릭으로 정의
⇒ 메서드의 선언부에 제네릭 타입이 선언된 메소드
class BoxFactory {
public static <T> Box<T> makeBox(T o) {
Box<T> box = new Box<T>(); // 상자를 생성하고,
box.set(o); // 전달된 인스턴스를 상자에 담아서,
return box; // 상자를 반환한다.
}
}
// 제네릭 메소드의 T는 메소드 호출시점에 결정됨
Box<String> sBox = BoxFactory.<String>makeBox("Sweet");
Box<Double> dBox = BoxFactory.<Double>makeBox(7.59); // 7.59에 대해 오토 박싱 진행됨
// 다음과 같이 타입 인자 생략 가능
Box<String> sBox = BoxFactory.makeBox("Sweet");
Box<Double> dBox = BoxFactory.makeBox(7.59); // 7.59에 대해 오토 박싱 진행됨
Java
복사
제네릭 메소드의 제한된 타입 매개변수 선언
// <T extends Number>는 타입 인자를 Number를 상속하는 클래스로 제한함을 의미
public static <T extends Number> Box<T> makeBox(T o) {
....
// 타입 인자 제한으로 intValue 호출 가능
System.out.println("Boxed data: " + o.intValue());
return box;
}
// 타입 인자를 Number를 상속하는 클래스로 제한
public static <T extends Number> T openBox(Box<T> box) {
// 타입 인자 제한으로 intValue 호출 가능
System.out.println("Unboxed data: " + box.get().intValue());
return box.get();
}
Java
복사