자바에서 제네릭의 공변, 반공변, 무공변에 대해 설명

김명수·2025년 12월 10일

매일메일

목록 보기
65/127
post-thumbnail

자바에서 제네릭의 공변, 반공변, 무공변에 대해 설명

●자바에서 제네릭의 공변, 반공변, 무공변에 대해 설명

  • 자바에서 제네릭(Generic) 은 기본적으로 무공변(Invariant) 이며, 무공변이란 타입 S, T가 있을 때 서로 관계가 없다는 것을 의미하며 S와 T가 서로 상속 관계이면 공변성이 있지만 제네릭은 상속 관계가 호환되지 않으며 따라서 타입이 정확히 일치하지 않으면 컴파일 에러가 발생
public class Animal {
}

public class Cat extends Animal {
}

List<Animal> animals = new ArrayList<Cat>(); // 컴파일 에러
List<Cat> cats = new ArrayList<Animal>(); // 컴파일 에러
  • 무공변은 타입 안정성을 보장하지만 타입의 유연성이 부족하다는 단점이 있어, 자바에서는 와일드카드(?)와 extends, super 키워드로 공변과 반공변을 지원

  • 공변(Covariant) 은 S가 T의 하위 타입일 때 S는 T가 될 수 있다는 것을 의미하며, 제네릭에서는 <? extends T>를 사용하여 하위 타입을 허용하고 읽기 전용으로 사용할 수 있으며, 쓰기는 null만 가능

  • 반공변(Contravariant) 은 S가 T의 하위 타입일 때 T는 S가 될 수 있다는 것을 의미하며, 제네릭에서는 <? super S>를 사용하여 상위 타입을 허용하고 쓰기 전용으로 사용할 수 있으며, 읽기는 Object 타입으로만 가능

●PECS란 무엇인가?

  • PECS(Producer Extends, Consumer Super) 는 제네릭에서 와일드카드의 상위 또는 하위 경계를 설정할 때 사용하는 가이드라인이며, 객체를 생산할 때는 <? extends T>를 사용하고, 소비할 때는 <? super T>를 사용
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>의 차이점은 무엇인가요?

  • < ?>와 < Object>는 모든 타입을 수용하는 것처럼 보이지만 동작 방식에 차이가 있음

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

profile
신입개발자

0개의 댓글