제네릭을 소개하기에 앞서 왜 쓰는지부터 파악해보자.
컴파일 단계에 형이 다르면 컴파일을 중지하고 에러를 반환하는걸 강타입 언어, 그렇지 않은걸 약타입 언어라 한다.
자바는 강타입 언어이다. 그런데 열심히 클래스를 설계하고 보니 int형만 처리하는게 아닌 double, 심지어 객체까지도 처리해야하는 상황이 생기면 각 타입마다 메서드를 새로 만들어야 할 것이다. 코드의 중복은 최악이다. 따라서 이를 해결하기 위해 제네릭이란걸 만들었다.
제네릭은 무엇인가
제네릭의 사전적 의미는 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법이다. 예를 들어 List 클래스는 Integer, Double 상관없이 받을 수 있다. 그렇다면 아무거나 상관없이 받는게 제일 좋은거 아닌가? 생각할 수 있겠지만 캐스팅을 할 수 없는 클래스는 오류를 발생시키는게 맞다.
List<Integer> intNums = new ArrayList<>();
intNums.add(1.1); //정수형 래퍼 클래스에 실수형을 넣으려 하면 오류를 발생시킴.
이런 식으로 타입을 한정시키는건 컴파일 단계에서 미리 실수를 잡아주어 사전에 방지할 수 있다는 장점을 갖고 있다.
관례적으로 제네릭은 영단어의 앞글자 대문자를 따와 의미를 갖는 클래스로 표현한다.
타입 | 설명 |
<T> | Type |
<E> | Element |
<K> | Key |
<V> | Value |
<N> | Number |

클래스 형변환을 통해 다형성을 구현한 것처럼 제네릭도 상속 관계를 나타내어 타입을 한정시킬 수 있다.
<T extends B> : T 자신과 B의 자식 클래스들을 받을 수 있음. (상한 경계)
<T super B> : T자신과 B의 조상 클래스들을 받을 수 있음. (하한 경계)
예를 통해 알아보자.
<T extends Comparable<B>>는 무슨 의미일 것 같은가? 먼저 T 자신이 포함되고, B를 비교하기 위해 Comparable을 상속하는 클래스를 받을 수 있다는 의미이다.
그런데 특별한 의미를 갖는 키워드가 있다. 바로 와일드 카드이다.
와일드 카드 타입은 무엇인가
범상치 않은 이름답게 표현도 특이하다. ?이다. 아무거나 상관없이 받을 수 있다는 의미이다. 즉, 자바의 최상위 클래스인 Object 클래스를 상속하는 어떤 클래스든 다 받을 수 있다.
그런데 앞서 아무거나 받지 않기 위해 한정시킨다 했는데, 아무거나 받을 수 있는 와일드 카드 타입이 있다. 자바 클래스 설계자 입장에서 보자. 클래스들이 한 두개가 아닌데, 이를 제네릭으로 다 표현할 수가 없다. 목적도 다르고 의미도 다르기 때문이다. 따라서 최상위를 받을 수 있는 와일드 카드를 만든 것이다.
예시) <E extends Comparable<? super E>> : E 자기 자신 및 조상 타입과 비교할 수 있는 E
'Java' 카테고리의 다른 글
리플렉션에 대하여 (0) | 2022.03.03 |
---|---|
Enum에 대하여 (0) | 2022.02.26 |
일급 컬렉션에 대하여 (0) | 2022.02.16 |
Optional에 대하여 (0) | 2022.02.10 |
Stream에 대하여 (0) | 2022.02.10 |