Java - Generics

진경천·2024년 9월 23일

Java

목록 보기
4/9

제네릭이란

<>(제너릭, 꺽쇠, 다이아몬드) 라고 불린다.
제네릭 안에 C++의템플릿 처럼 T or E 등 타입을 변수로 선언.
타입이 변수로 선언되기에 타입에 상당히 유연해진다.

제네릭의 특징

  • 컴파일 타임에 타입 검사
    ➡️ 예외 방지

  • 불필요한 캐스팅 제거

  • 제네릭 타입의 객체는 생성 불가

  • static 멤버에 제네릭 타입이 올 수 없음

public static T add(int n){ }
public static void add(T n){ }
// error
  • 제네릭 배열 선언 주의
    제네릭 클래스를 배열로 만들 수는 없지만 제네릭 타입의 배열 선언은 허용된다.

제네릭 외에도 타입을 Object로 사용하는 방법도 있지만 객체를 호출할 때 번거로움이 생길 수 있다.

와일드 카드

등장 배경

제네릭은 불공변이기 때문에 모든 타입에서 공통적으로 사용되는 메서드를 만들기 어려웠다.
IntegerObject의 하위 타입이지만 List<Integer>List<Object>의 하위타입이 아니기 때문

그렇기 때문에 아래와 같은 와일드 카드가 등장하였다.

와일드 카드 네이밍 설명
<?> Unbounded 제한없음 (모든 타입 가능)
<? extends U> Upper bounded 상위 클래스 제한 (U와 그 자손들만 가능)
<? super U> Lower bounded 하위 클래스 제한 (U와 그 조상들만 가능)

이에 대해 이해하려면 우선 공변성에 대해 알아야한다.

공변성

하위 타입이 상위 타입을 참조 가능
S 가 T 의 하위 타입이면,

S[]T[] 의 하위 타입이다.
List<S>List<T> 의 하위 타입이다.

Integer[] intArray = {1, 2, 3};
Object[] objArray = intArray; // 공변성: Integer[]는 Object[]로 변환 가능

List<? extends Number> numberList = new ArrayList<Integer>(); // Integer는 Number의 하위 타입

반공변성

상위 타입이 하위 타입을 참조 가능

S 가 T의 하위 타입이면,

T[]S[] 의 하위 타입이다. (공변의 반대) 
List<T> 는 List<S> 의 하위 타입이다. (공변의 반대)

List<? super Integer> superList = new ArrayList<Number>(); // Number는 Integer의 상위 타입

불공변

상/하위 타입 여하를 떠나 참조가 불가함.

S 와 T 는 서로 관계가 없다.
List<S>List<T> 는 서로 다른 타입이다.

List<Number> numberList = new ArrayList<Integer>(); // 컴파일 에러

제너릭은 공변성 / 반공변성을 지원하지 않는다! 즉, 무공변의 성질을 지닌다.
그러므로 제너릭은 전달받은 타입으로만 캐스팅이 가능하다.

정리

개념 설명 예시
공변 하위 타입이 상위 타입을 참조 가능 배열 (Integer[] -> Object[]), List<? extends Number>
반공변 상위 타입이 하위 타입을 참조 가능 List<? super Integer>
불공변 상위 타입과 하위 타입이 참조 불가 List<Number>와 List<Integer>는 서로 참조 불가
profile
어중이떠중이

0개의 댓글