티스토리 뷰
Generics를 사용하면서 재사용성을 높이기 위한 방법으로 이름조차 버거운 한정적 와일드카드 타입이 있다
한정적 와일드카드 타입을 이해하기에 앞서 Generics의 불공변을 이해하기 위해
List<String>과 List<Object>을 살펴보자, 둘은 어떠한 관계도 없는 다른 타입이다
List<Object>에는 기본형을 제외한 모든 객체 타입을 넣을 수 있는데 List<String>에는 오직 String 타입만 넣을 수 있다
책에서는 상하위 관계에서 지켜져야 할 리스코프 치환 원칙을 지키지 않기 때문에 둘은 다른 타입이라 말한다
따라서 논리적으로도 맞고 타입 안전한 개발이 가능하지만 아쉬운 점이 있다
Generics은 정말 좋지만 타입 매개변수에 직접 타입을 지정해버리면 그 타입에 한정되어 굳어버린다
사용하려는 매개변수 타입 개수 만큼의 메서드를 만들어야 한다
이 말은 재활용성이 떨어지게 된다는 것인데 이러한 상황에 딱 맞는 것이 한정적 와일드카드 타입이다
어디선가 봤을 <? extends E>, <? super E> 따위를 말하는 것인데
extends E는 E를 포함하고 그 하위로 쭉, super E는 E를 포함하고 그 상위로 쭉을 의미한다
이하 조건, 이상 조건으로 외우면 쉽다, 이 것들을 언제 쓰면 좋은가?
PECS 공식이라 하여 producer-extends, consumer-super로 알고 있으면 된다
물론 더 깊이 들어가서 이해하는게 가장 좋지만 제네릭도 낯선데 한정적 와일드카드를 바로 이해하기란 쉽지 않다
따라서 초반엔 PECS 공식을 외워두면 반은 먹고 들어간다
그렇다면 어느 상황이 생산하고, 어느 상황이 소비하는 것인가?
parameter로 넘어오는 컬렉션 또는 다양한 객체를 이용해 무엇을 하는지를 기준 삼으면 된다
즉, 넘어온 애를 형태는 달라도 다시 반환하느냐, 아니면 사용만 하고 반환하지 않느냐가 기준이다
1. 넘어온 애로 다른 컬렉션으로 만들어 반환하는 경우
2. 넘어온 애들을 합쳐서 다른 컬렉션으로 반환하는 경우
요소를 이용해 무언가를 생산했으므로 producer다
1. 넘어온 애로 다른 컬렉션에 pop 같이 빼는 작업을 하는 경우
2. 넘어온 애로 compare 같이 비교를 수행하고 비교된 값을 넘겨주는 경우 (Comparable)
요소를 사용해 특정 작업을 하여 소비했으므로 consumer다
제네릭을 더 깊이 이해하는데 기똥찬 블로그가 있어 두개 소개한다
https://asuraiv.tistory.com/16?category=813980
https://yaboong.github.io/java/2019/01/19/java-generics-1/
첫 번째 블로그에서는 임백준 님의 저서에서 나온
제네릭은 지나치게 복잡도를 높이기 때문에 좋지 않다는 의견을 인용했는데 나는 이에 대해 반대의 생각을 갖고 있다
한정적 와일드카드 타입을 사용하면 재사용성 높은 메서드를 만들 수 있다는 점은 반박 불가한데
단점이 누구나 이해하기 쉽지는 않다는 것이다
난 멋지지만 어려운 방식보다 명확한 방식이 훨씬 낫다고 생각한다
그렇다고 추후 유지보수를 생각하면 타입 별로 메서드를 와장창 만들 순 없지 않나
또한 변성이라는 개념은 자바에만 국한된 것도 아니고 공부해보면 말로 풀어내기는 힘들어도 직관적으로 이해되기는 한다
따라서 복잡도와 효용성을 비교해 선택하면 되는데
나는 그리 어려운 개념이라 생각하지 않기 때문에 한정적 와일드카드 타입을 사용해야 한다고 생각한다
더 큰 이유는 자바 & 스프링도 진작 쓰고 있다, 이해하기 어렵다고 자바 & 스프링 코드를 안 보고 넘겨버릴 순 없다
한정적 와일드카드 타입이 여러 개 중첩된 아찔한 메서드는 반대하지만
약간의 학습으로 재사용성을 높일 수 있다는데 안 쓸 이유가 없지 않은가?
'Java > Effective Java' 카테고리의 다른 글
[Item33] Super Type Tokens (0) | 2022.03.13 |
---|---|
[Item32] varargs는 신중히 (0) | 2022.03.11 |
[Item30] 따봉 제네릭스 (0) | 2022.03.09 |
[Item29] 이왕이면 제네릭 써라 (0) | 2022.03.07 |
[Item28] 배열 : 제네릭 = 공변 : 불공변 (0) | 2022.03.07 |