작성한 클래스 또는 메서드의 코드가 특정 데이터 타입에 얽매이지 않게 해둔 것을 의미한다.
제네릭이 사용된 클래스를 제네릭 클래스라고 한다.
T
를 타입 매개변수라고 하며, <T>
와 같이 꺽쇠 안에 넣어 클래스 이름 옆에 작성해줌으로써 클래스 내부에서 사용할 타입 매개변수를 선언할 수 있다.
타입 매개변수는 임의의 문자로 지정할 수 있다.
제네릭 클래스를 정의할 때 주의할 점
제네릭 클래스는 멤버를 구성하는 코드에 특정한 타입이 지정되지 않은 클래스이므로, 제네릭 클래스를 인스턴스화할 때에는 의도하고자 하는 타입을 지정해주어야 한다.
Basket<String> basket1 = new Basket<>("Hello");
Basket<Integer> basket2 = new Basket<>(10);
Basket<Double> basket2 = new Basket<>(3.14);
제한된 제네릭 클래스
class Flower { ... }
class Rose extends Flower { ... }
class RosePasta { ... }
class Basket<T extends Flower> {
private T item;
...
}
public static void main(String[] args) {
// 인스턴스화
Basket<Rose> roseBasket = new Basket<>();
Basket<RosePasta> rosePastaBasket = new Basket<>(); // 에러
}
interface Plant { ... }
class Flower implements Plant { ... }
class Rose extends Flower implements Plant { ... }
class Basket<T extends Plant> {
private T item;
...
}
public static void main(String[] args) {
// 인스턴스화
Basket<Flower> flowerBasket = new Basket<>();
Basket<Rose> roseBasket = new Basket<>();
}
클래스 전체를 제네릭으로 선언할 수도 있지만, 클래스 내부의 특정 메서드만 제네릭으로 선언할 수 있다.
class Basket {
...
public <T> void add(T element) {
...
}
}
제네릭 메서드의 타입 매개변수는 제네릭 클래스의 타입 매개변수와 별개의 것이다.
아래와 같이 동일하게 T
라는 타입 매개변수명을 사용한다 하더라도, 같은 알파벳 문자를 이름으로 사용하는 것일뿐, 서로 다른 타입 매개변수로 간주된다.
class Basket<T> { // 1 : 여기에서 선언한 타입 매개변수 T와
...
public <T> void add(T element) { // 2 : 여기에서 선언한 타입 매개변수 T는 서로 다른 것입니다.
...
}
}
클래스명 앞에서 선언한 타입 매개변수는 클래스가 인스턴스화 될 때 타입이 지정되지만
제네릭 메서드 타입 지정은 메서드가 호출될 될 때 이루어진다.
또한 클래스 타입 매개변수와 달리 메서드 타입의 매개변수는 static
메서드에서도 선언하여 사용할 수 있다.