목차
· 변성
· 제네릭과 공변/무공변
· 와일드카드 타입과 공변/반공변
· 사용지점 변성과 선언 지점 변성
변성
변성(Variance)은 타입의 계층 관계에서 서로 다른 타입 간에 어떤 관계가 있는지 나타내는 개념이다.
해당 개념은 자바의 제네릭을 설명하기 위해 자주 사용된다.
변성에는 네 가지 종류가 있다.
공변(covariant), 반공변(contravariant), 이변량(bivariant), 무공변(or 불공변, invariant)
이 중에서 알아볼 것은 공변, 반공변, 무공변이다.
제네릭과 공변/무공변
공변은 사전적 의미로 '함께 변하는'이라는 뜻이다.
제네릭은 기본적으로 무공변(or 불공변, invariant)이다.
즉, 서로 다른 타입 Type1과 Type2가 있을 때, List<Type1>은 List<Type2>의 하위 타입도 아니고 상위 타입도 아니라는 뜻이다.
이와 반대로 배열은 공변이다.
즉, Sub 타입이 Super 타입의 하위 타입이라면, 배열 Sub[]은 배열 Super[]의 하위 타입이다.
와일드카드 타입과 공변/반공변
하지만 제네릭이 이렇게만 사용되면, 제네릭의 표현은 너무 한정적이게 된다.
따라서 제네릭에는 '한정적 와일드카드 타입'이라는 기능이 제공된다.
타입 매개변수에 <? extends Type>를 선언하면 타입 매개변수에 공변이 선언될 수 있다.
즉, 아래코드에 src 매개변수에는 'E의 하위 타입의 Iterable'만 입력될 수 있다.
public void pushAll(Iterable<? extends E> src) {
for( E e : src )
push(e);
}
반대로, 타입 매개변수에 <? super Type>를 선언하면 타입 매개변수에 반공변(contravariance)이 선언될 수 있다.
즉, 아래코드에 src 매개변수에는 'E 상위 타입의 Iterable'만 입력될 수 있다.
public void pushAll(Iterable<? super E> src) {
for( E e : src )
push(e);
}
사용지점변성과 선언지점변성
앞서 살펴본대로 자바에는 한정적 와일드카드 타입을 통해 타입의 공변성 또는 반공변성을 지정할 수 있다.
이렇게 타입 파라미터가 나타나는 지점에 변성을 정하는 자바의 방식을 사용지점변성(use-site variance)이라 한다.
어떠한 타입 T의 공변성을 허용하려면 <? extend T>를 사용한다.
어떠한 타입 T의 반공변성을 허용하려면 <? super T>를 사용한다.
자바와 같이 JVM을 이용하는 언어인 코틀린에서도 사용자 지점 변성을 제공한다.
코틀린에서는 사용 지점 변성을 out과 in 키워드를 이용해 지원한다.
자바의 <? extend T>가 코틀린에서는 <out T>이다.
자바의 <? super T>가 코틀린에서는 <in T>이다.
여기에 추가적으로 선언지점변성을 제공한다. 선언 지점 변성은 클래스를 선언할 때 공변성을 지정한다.
즉, 클래스 전역에 공변성을 지정할 수 있다.
class Box<out T>(val data: T)
이러한 선언 지점 변성은 타입 파라미터마다 변성을 계속 지정해야 하는 사용 지점 변성의 단점을 개선한다.
출처
이펙티브자바
https://asuraiv.tistory.com/16
https://sungjk.github.io/2021/02/20/variance.html
https://dzone.com/articles/variance-in-java
'자바' 카테고리의 다른 글
[Java] 자바에서 XML을 파싱하는 방법 - DOM, SAX (0) | 2021.12.14 |
---|---|
[JAVA] 자바에서 파일, 디렉터리 변경 사항을 감지하는 방법 - WatchService (0) | 2021.12.13 |
[Java] 자바8의 새로운 날짜 관련 클래스들 - java.time 패키지 (LocalDate, LocalTime, LocalDateTime, ZonedDateTime) (0) | 2021.12.13 |
[Java] 런타임에 자바 코드를 조작하는 방법: 리플렉션(Reflection) (0) | 2021.12.10 |
[Java] JDK가 제공하는 기본 개발 도구 (javac, java, javadoc, jps, jmap) (0) | 2021.12.06 |
댓글