상세 컨텐츠

본문 제목

[매일메일] 자바에서 제네릭의 공변, 반공변, 무공변에 대해 설명해주세요

본문

??

제네릭은 자바에서 내부에서 사용할 데이터 타입에 대해서 정의하고 지정하는 것을 말한다고 한다.

공변이 영어로 적혀 있는 것을 보면 covariant라고 한다. 제네릭의 공변이 서브타입 관계를 그대로 따라가는 것을 의미한다고 한다.

예를 들어 Dog가 Animal 서브클래스라면, List[Dog]는 List[Animal]의 서브타입으로 인정된다. 이때 반공변은 서브타입 관계가 반대로 적용된다고 한다. 이때 무공변이라면 서브타입 관계를 인정하지 않는다고 한다.

 

서브타입이란, 객체지향 프로그래밍에서 한 타입이 다른 타입의 하위 타입임을 의미한다고 한다.

자식 클래스가 부모 클래스의 서브 타입 이라고 생각하면 된다고 한다.

즉, is-a 관계로 이 타입을 이 자리에 대신 써도 문제가 없는가를 의미한다고 한다. (아하)

 

자바에서는 ?와 extends, super등의 키워드로 공변과 반공변을 지원한다고 한다.

공변의 경우,

<? extends T>를 사용하여 하위 타입을 허용하고 읽기 전용으로 사용 가능하다 한다.

 

반공변의 경우,

<? super S> 를 사용하여 상위 타입을 허용하고 쓰기 전용으로 사용 가능하다고 한다. 읽기는 Object 타입으로만 가능하다.

 

PECS (Producer Extends, Consumer Super)

예시 코드:

public void produce(List<? extends Animal> animals) { // animals가 생산자 역할
    for (Animal a : animals) {
        System.out.println(a);
    }
}

public void consume(List<? super Cat> cats) { // cats가 소비자 역할
    cats.add(new Cat());
}

이떄 <?>와 <Object>의 차이는 <?>는 모든 타입을 메서드 인자로 받을 수 있지만, null외에는 값을 추가할 수 없기 때문에 읽기 전용으로 사용된다. <Object>는 <Object>외의 타입을 메서드 인자로 받을 수 없지만 모든 객체를 추가할 수 있기 때문에 읽기, 쓰기 모두 가능하다.

 

관련글 더보기