클래스 전체를 제네릭으로 선언할 수 있는 것처럼, 클래스 내부의 특정 메서드만 제네릭으로 선언 할 수도 있음.
class Basket {
...
public <T> void add(T element) {
...
}
}
제네릭 메서드의 타입 매개변수 선언은 반환 타입 앞에서 이루어지며, 해당 메서드 내에서만 타입매개변수를 사용할 수 있음.
제네릭 메서드의 타입 매개변수는 제네릭 클래스의 타입 매개변수와 별개의 것이다.
class Basket<T> { // 1 : 여기에서 선언한 타입 매개변수 T와
...
public <T> void add(T element) { // 2 : 여기에서 선언한 타입 매개변수 T는 서로 다른 것
...
}
}
이렇게 되는 이유 : 클래스명 옆에서 선언한 타입 매개변수는 클래스가 인스턴스화 될 때 타입이 지정됨. 그러나 제네릭 메서드의 타입은 메서드가 호출 될 때 지정됨.
Basket<String> basket = new Bakset<>(); // 위 예제의 1의 T가 String으로 지정됩니다.
basket.<Integer>add(10); // 위 예제의 2의 T가 Integer로 지정됩니다.
basket.add(10); // 타입 지정을 생략할 수도 있습니다.
클래스 타입 매개변수와 달리 메서드 타입 매개변수는 static 메서드에서도 선언하여 사용 가능.
class Basket {
...
static <T> int setPrice(T element) {
...
}
}
제네릭 메서드는 메서드가 호출 되는 시점에 타입이 결정됨. 제네릭 메서드를 정의하는 시점에는 실제 어떤 타입이 들어올지 알 수 없기 때문에 length()와 같은 String 클래스의 메서드는 제네릭 메서드를 정의하는 시점에 사용할 수 없음.
class Basket {
public <T> void print(T item) {
System.out.println(item.length()); // 불가
}
}
하지만 모든 자바 클래스의 최상위인 Object 클래스의 메서드는 사용 가능
class Basket {
public <T> void getPrint(T item) {
System.out.println(item.equals("Kim coding")); // 가능
}
}