타입 파라미터를 한 개 이상 받는 클래스
example
@Getter
public class Entry<K, V> {
private final K key;
private final V value;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
Entry<String, Integer> 클래스는
String getKey(), Integer getValue() 메서드를 가진다.
Entry<String, Integer> entry = new Entry<>("salary", 100);
와 같이 객체를 생성할 때 생성자에서 타입 파라미터를 생략할 수 있다.
다이아몬드 문법이라고 한다. 타입을 추론한다.
public class Arrays {
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
...
}
타입 파라미터를 받는 메서드. 일반 클래스나 제네릭 클래스의 멤버가 될 수 있다.
선언 시 타입 파라미터를 제어자와 반환타입 사이에 둔다.
메서드 선언 시 타입 파라미터를 명시하지 않아도 컴파일러가 추론해준다.
원한다면 메서드 이름 앞에 명시한다.
Arrays.<String>sort(stringList, null);
public static <T extends AutoCloseable> void closeAll(ArrayList<T> elements) throws Exception {
for (T element : elements) {
element.close();
}
}
위 타입 경계 지정은 T 가 AutoCloseable의 서브타입임을 보장한다. 인터페이스, 클래스 상관없이 extends 키워드만 쓴다.
ArrayList<PrintStream>
은 전달할 수 있지만, ArrayList<String>
은 전달할 수 없다.
T extends Runnable & AutoCloseable
과 같이 다중 경계도 지정 가능하다.
public static void printNames(ArrayList<? extends Employee> staffs) {
for (Employee employee : staffs) {
System.out.println(employee.getName());
}
}
public static void printAll(Employee[] employees, Predicate<? super Employee> filter) {
for (Employee employee : employees) {
if (filter.test(employee)) {
System.out.println(employee.getName());
}
}
}
제네릭 타입을 정의하면 해당 타입은 로(raw) 타입으로 컴파일된다.
ex)
@Getter
public class Entry<K, V> {
private final K key;
private final V value;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
to
public class Entry {
private final Object key;
private final Object value;
public Entry(Object key, Object value) {
this.key = key;
this.value = value;
}
public Object getKey() {
return key;
}
public Object getValue() {
return value;
}
}
ArrayList<String> list = (ArrayList<String>) result;
와 같은 경우 result가 raw ArrayList 인지만 검사한다.
T(...), new T[...] 와 같은 표현식 사용 불가
Entry<String, Integer>[] entries = new Entry<String, Integer>[100];
불가
제네릭 클래스의 객체는 예외로 던지거나 잡아낼 수 없다.
public class Problem<T> extends Exception
불가. 제네릭 클래스는 Throwable의 서브타입이 될 수 없다