Home Generic 과 조금 더 친해지기
Post
Cancel

Generic 과 조금 더 친해지기

제네릭이란?

상속관계에 대한 타입 안정성을 지키고 유연하게 타입을 확장할 수 있도록 도와주는 기능이다.

1
2
3
4
5
6
7
public class MyCustomList<T> {

    public void addElement(T element) {
        list.add(element);
    }

}

위와 같이 제네릭 타입을 매개변수로 받는 메서드를 만들면 어떤 타입이 와도 관계없이 메서드를 사용할 수 있다.

이때, 제네릭을 선언한 클래스에서 모든 메서드나 변수의 타입을 처럼 특정 타입으로 맞춰주어야한다.

또한 제네릭 키워드 <> 안에는 대문자가 들어와야한다.


공변성 (Covariance)

공변성은 특정 객체의 타입이 다른 객체의 타입보다 더 구체적일 때, 이를 허용하는 속성이다.

List<? extends T>와 같은 방식으로 공변성을 나타낼 수 있다.

이는 T 타입 또는 T의 하위 타입의 객체들만을 담을 수 있는 List를 의미한다.

Repository, Reposioryextends하는 하위 ?들을 허용한다.

1
2
3
4
5
6
7
8
9
10
public class Covariance {

    public static void main(String[] args) {
        List<? extends Repository> covarianceRepositories = new ArrayList<>();

        // covarianceRepositories.add(new Repository()); 컴파일 에러
        // covarianceRepositories.add(new UserRepository()); 컴파일 에러
        // covarianceRepositories.add(new PostRepository()); 컴파일 에러
    }
}

List<? extends Repository>Repository의 모든 하위 타입을 포함할 수 있으므로, 컴파일러는 이 리스트가 UserRepository만을 담는 리스트인지, PostRepository만을 담는 리스트인지, 아니면 둘 다를 담을 수 있는 리스트인지 알 수 없다.

따라서, 타입 안전성을 위배하지 않도록, 이러한 리스트에는 새로운 요소를 추가할 수 없다.


반공변성 (Contravariance)

반공변성은 특정 객체의 타입이 제네릭으로 명시된 타입보다 더 상위계층일 때, 이를 허용하는 속성이다.

List<? super T>와 같은 방식으로 반공변성을 나타낼 수 있다.

이는 T 타입 또는 T의 상위 타입의 객체들을 담을 수 있는 List를 의미한다.

Repository, Reposiorysuper로 취급하는 상위 ?들을 허용한다.

1
2
3
4
5
6
7
8
9
public class Contravariance {

    public static void main(String[] args) {
        List<? super Repository> contravariantList = new ArrayList<>();
        contravariantList.add(new Repository());
        contravariantList.add(new UserRepository());
        contravariantList.add(new PostRepository());
    }
}

List<? super Repository>Repository 또는 그 상위 타입의 객체들만을 담을 수 있다.

Repository는 UserRepository와 PostRepository의 상위 타입이기 때문에 리스트가 어떤 타입의 객체들을 받을 수 있는지 명확하므로

타입 안전성을 유지할 수 있어 컴파일 에러가 발생하지 않는다.


불공변성 (Contravariance)

불변성은 특정 객체의 타입이 정확히 일치할 때만 해당 타입의 객체들을 담을 수 있게 하는 속성이다.

제네릭에서는 기본적으로 불변성이 적용된다.

이는, List는 T 타입의 객체들만 담을 수 있다.

T에 해당하는 타입들만 허용한다. (제네릭의 기본 값이다.)

1
2
3
4
5
6
7
8
9
public class Invariance {

    public static void main(String[] args) {
        List<Repository> invariantList = new ArrayList<>();
        invariantList.add(new Repository());
        invariantList.add(new UserRepository());
        invariantList.add(new PostRepository());
    }
}
This post is licensed under CC BY 4.0 by the author.