데이터 타입(data type)을 일반화(generalize)한다.
public class ExampleList<E, U> {...}
E
, U
,
로 구분한다.T
: TypeE
: ElementK
: KeyV
: ValueN
: NumberR
: Resultpublic class 클래스명<T> {...}
public interface 인터페이스명<T> {...}
class GenericClass<T> {
T element;
void setElement(T element) {
this.element = element;
}
T getElement() {
return element;
}
}
interface GenericInterface<T> {
T print();
}
class GenericImpl implements GenericInterface<String> {
@Override
public String print() {
return "generic interface";
}
}
public class Pair<K, V> {...}
public class Util {
public static<K, V> boolean compare(Pair<K, V> pair1, Pair<K, V> pair2) {
return pair1.getKey().equals(pair2.getKey()) &&
pair1.getValue().equals(pair2.getValue());
}
}
public class GenericApplication {
public static void main(String[] args) {
Pair<String, Integer> pair1 = new Pair<>("abc", 1);
Pair<String, Integer> pair2 = new Pair<>("def", 1);
boolean isSame = Util.<String, Integer>compare(pair1, pair2);
}
}
class GenericClass<T, U>
내에 <T, K> void test()
메서드가 있더라도 각자의 타입 인자 T
는 전혀 상관 없다.// 1. type parameter 지정
MyArray<Integer> myArray = new MyArray<Integer>();
// 2. type parameter 추정
MyArray<Integer> myArray = new MyArray<>();
자바 코드에서 선언, 사용된 generic type은 컴파일 시 컴파일러에 의해 자동으로 검사되고 타입이 변환된다.
그 후 generic을 사용하지 않는 코드와의 호환성을 유지하기 위해 코드의 모든 generic type은 제거되고, 컴파일된 class 파일에는 어떠한 generic type도 포함하지 않는다.
?
키워드<?>
Class<T>
의 대부분의 메서드는 T에 의존하지 않기 때문에 Class<?>
가 자주 사용된다.public static void printList(List<Object> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
List<Integer>
, List<String>
, List<Double>
등은 List<Object>
의 위 메서드를 사용할 수 없다.
public static void printList(List<?> list) {
for (Object elem: list)
System.out.print(elem + " ");
System.out.println();
}
모든 타입이 위 메서드 사용 가능
List<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strs = Arrays.asList("one", "two", "three");
printList(ints); // 1 2 3
printList(strs); // one two three
<? extends 상위타입>
extends
나 implements
로 표현하는 구체 타입, 서브 타입public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list)
s += n.doubleValue();
return s;
}
List<Integer> ints = Arrays.asList(1, 2, 3);
System.out.println("sum = " + sumOfList(ints)); // 6.0
List<Number>
이 List<? extends Number>
보다 제한적이다.<? super 하위타입>
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
ArrayList arrayList = new ArrayList();
arrayList.add("element");
String str = (String) arrayList.get(0);
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("element");
String str = arrayList.get(0);
class LandAnimal {
public void cry() {
System.out.println("육지동물");
}
}
class Cat extends LandAnimal {
public void cry() {
System.out.println("냐옹");
}
}
class Dog extends LandAnimal {
public void cry() {
System.out.println("멍멍");
}
}
class Bird {
public void cry() {
System.out.println("짹짹");
}
}
class AnimalList<T> {
ArrayList<T> animals = new ArrayList<T>();
void add(T animal) {
animals.add(animal);
}
T get(int index) {
return animals.get(index);
}
boolean remove(T animal) {
return animals.remove(animal);
}
int size() {
return animals.size();
}
}
public class GenericApplication {
public static void main(String[] args) {
AnimalList<LandAnimal> landAnimals = new AnimalList<>();
landAnimals.add(new LandAnimal());
landAnimals.add(new Cat());
landAnimals.add(new Dog());
// landAnimals.add(new Bird()); // 오류 발생
for (int i = 0; i < landAnimals.size(); i++) {
landAnimals.get(i).cry();
}
}
}
<실행 결과>
육지동물
냐옹
멍멍