티스토리 뷰
제네릭의 의미
제네릭 클래스, 제네릭 인터페이스, 제네릭 메소드
-클래스, 인터페이스, 메소드를 정의할 때 타입 매개변수(타입 파라미터)를 선언하고 사용할 수 있음
제네릭을 사용하는 이유
- 자료형을 한정함으로써 컴파일 시점에 자료형 검사가 가능
* 실행 오류를 찾아 고치는 것은 어려움
- 캐스트(형변환) 연산자의 사용이 불필요
- 여러 유형에 걸쳐 동작하는 일반화된 클래스/메소드를 정의할 수 있음
ArrayList 클래스는 List 인터페이스를 구현한 클래스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class ArrayList<E> implements List<E> … { boolean add(E e) { … } E get(int index) { … } E remove(int index) { … } … } | cs |
1 2 3 4 5 6 | List list1 = new ArrayList(); list1.add("hello"); String s1 = (String)list1.get(0); // 형변환 필요 List<String> list2 = new ArrayList<String>(); list2.add("hello"); String s2 = list2.get(0); //형변환이 필요 없음 | cs |
제네릭 클래스
클래스 정의에서 타입 파라미터를 선언함
- 클래스를 사용할 때는 타입을 명시해야 함
- 필드의 자료형, 메소드 반환형, 인자의 자료형으로 사용할 수 있음
타입 파라미터는 참조형만 가능함
컴파일 할 때, 명확한 타입 검사를 수행할 수 있음
- 메소드 호출시 인자의 유형이 맞는지
- 메소드 호출의 결과를 사용할 때 유형이 맞는지
자료형을 매개변수로 가지는 클래스와 인터페이스를 제네릭 타입이라고 함
제네릭 클래스 정의
문법
1 | class 클래스이름<T1, T2, …> { … } | cs |
- 클래스 정의에서 클래스 이름의 오른편, 각 괄호 < > 안에 타입 파라미터를 표시함
- 컴마(,)로 구분하여 여러 개의 타입 파라미터를 지정할 수 있음
- 타입 파라미터는 타입을 전달 받기 위한 것
- 타입 파라미터의 이름은 관례적으로 E, K, V, N, T … 을 사용함
1 2 3 4 5 6 7 8 9 10 11 | class Data { private Object object; public void set(Object object) { this.object = object; } public Object get() { return object; } } | cs |
1 2 3 4 5 6 7 8 9 10 11 | class Data2<T> { private T t; public void set(T t { this.t = t; } public T get() { return t; } } | cs |
제네릭 클래스의 사용
제네릭 타입과 자료형 검사
- 제네릭 타입을 사용하지 않으면 컴파일 시점에서 오류를 검출하지 못함
의미가 명확하면 생성자 호출 시, 괄호만 사용할 수 있음
1 | Data2<String> b3 = new Data2<>(); | cs |
1 2 3 4 5 6 7 8 9 | public class GenericsTest2 { public static void main(String args[]) { Data2<String> data = new Data2<String>(); Integer i = new Integer(20); data.set(i); // 컴파일 오류 String s = (String)data.get(); … … } } | cs |
제네릭 인터페이스를 구현하는 제네릭 클래스
2개의 타입 매개변수(K와 V)를 가지는 클래스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | interface Pair<K, V> { public K getKey(); public V getValue(); } class OrderedPair <K, V> implements Pair <K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } public class MultipleType { public static void main(String args[]) { Pair <String, Integer> p1; p1 = new OrderedPair <> ("Even", 8); Pair <String, String> p2; p2 = new OrderedPair <> ("hello", "java"); … … } } | cs |
제네릭 타입을 상속/구현하는 일반 클래스
제네릭 인터페이스를 구현하는 일반 클래스
- 클래스를 정의할 때 제네릭 인터페이스의 자료형을 지정하면 됨
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class MyPair implements Pair<String, Integer> { private String key; private Integer value; public MyPair(String key, Integer value) { this.key = key; this.value = value; } public String getKey() { return key; } public Integer getValue() { return value; } } public class ClassFromGeneric { public static void main(String args[]) { MyPair mp = new MyPair("test", 1); … … } } | cs |
Raw 타입
제네릭 타입을 일반 타입처럼 사용하는 경우의 제네릭 타입을 지칭하는 용어
1 | Data2 data = new Data2("hello"); | cs |
- 이때 Data2는 제네릭 타입 Data2<T>의 raw 타입
- 자료형을 Object로 처리함