제네릭이란 무엇인가요?

  • 자바에서 제네릭(Generic) 이란, 클래스 내부에서 사용할 데이터 타입을 외부에서 저장하는 기법을 의미하며, 객체별로 다른 타입의 자료가 저장될 수 있도록 한다.

  • 컴파일 타임에 타입을 체크함으로써 코드의 안전성을 높여주는 기능을 가지고 있다.

img_30.png
  • 제네릭은 다이아몬드 연산자라고 하는 <> 꺾쇠 괄호 키워드를 사용한다.

  • 그리고 이 꺾쇠 괄호 안에 식별자 기호를 지정해 파라미터화할 수 있다.

  • 이것을 마치 메서드가 매개변수를 받아 사용하는 것과 비슷하여 제네릭의 타입 매개변수(parameter) / 타입 변수 라고 부른다.

타입 파라미터 기호 네이밍(암묵적인 규칙)

타입
설명

< T >

타입(Type)

< E >

요소(Element)

< K >

키(Key)

< V >

리턴 값 또는 매핑된 값(Variable)

< N >

숫자(Number)

< S, U, V >

2번째, 3번째, 4번째에 선언된 타입

제네릭을 사용했을 때 이점

  1. 컴파일 타임에 강력한 타입 검사를 통해 예외 방지

    • 제네릭이 나오기 전 자바 1.5 이전에는 Object 를 사용해 제네릭과 비슷하게 구현했다.

    • 이럴 경우 개발자가 일일이 타입 변환을 시도해야 하며, 실수할 가능성이 존재한다.

    • 하지만 제네릭을 사용하면 컴파일 타임에 미리 에러를 잡아주기 때문에 실수를 사전에 방지할 수 있다.

  2. 불필요한 캐스팅 제거

    • 제네릭 없이 Object를 사용하면 매번 다운 캐스팅을 통해 객체를 가져와야 한다.

    • 제네릭을 사용하면 미리 타입을 지정하여 제한하기 때문에 형 변환의 번거로움을 줄일 수 있다.

변성(variance)

이 코드는 가능할까? IntegerObject의 하위 타입이지만 컴파일 오류가 발생한다.

이와 같이 배열에서는 IntegerObject의 하위 타입이 성립이 된다. 이를 공변이라 한다.

하지만 제네릭 같은 경우는 ObjectInteger를 서로 관계가 없다고 보는데 이를 무공변 또는 불공변이라고 한다.

무공변(Invariance) - < T >

  • ST가 서로 관계가 없다.

    • List< S >List<T>는 서로 다른 타입이다.

공변(Covariance) - <? extends T>

  • 상위 타입에서 하위 타입으로 형 변환이 가능한 경우 타입을 공변 타입으로 간주한다.

  • ST의 하위 타입이면

    • S[]T[]의 하위 타입이다.

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

반공변(Contravariance) - <? super T>

  • 하위 타입에서 상위 타입으로 형 변환이 가능한 경우 타입을 반공변 타입으로 간주한다.

    • ST의 하위 타입이면

      • T[]S[] 의 하위 타입이다.(공변의 반대)

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

제네릭 와일드카드

  • 제네릭은 extendssuper 키워드를 이용해 클래스 상속 관계에서 타입을 하위 타입으로 제한할지, 상위 타입으로 제한할지 타입을 제한할 수 있다.

  • extends는 타입 파라미터에 특정 타입의 하위 타입만을 허용하도록 지정할 때 사용한다.

  • super는 타입 파라미터에 특정 타입의 상위 타입만을 허용하도록 지정할 때 사용한다.

와일드 카드
네이밍
설명

<?>

Unbounded wildcards

제한 없음(모든 타입 가능)

<? extends U>

Upper Bounded Wildcards 상한 경계 와일드카드

- 상위 클래스 제한 (U와 그 자손들만 가능) - 상한이 U라 상한 경계라고 한다.

<? super U>

Lower Bounded Wildcards 하한 경계 와일드카드

- 하위 클래스 제한 (U와 그 조상들만 가능) - 하한이 U라 하한 경계라고 한다.

extends / super 사용시기

  • 언제 <? extends T>를 사용하고, <? super T>를 사용해야 할까?

  • PECS

    • Producer-Extends / Consumer-Super의 약자다.

    • 외부에서 온 데이터를 생산(Producer)한다면 <? extends T>를 사용한다.(하위 타입으로 제한)

    • 외부에서 온 데이터를 소비(Consumer)한다면 <? super T>를 사용한다.(상위 타입으로 제한)

참고

Last updated