Study/Effective-Java

[item#26] 로(raw) 타입은 사용하지 말라

hongeeii 2023. 11. 30. 10:55
728x90
반응형

로(raw) 타입은 사용하지 말라

제네릭 클래스(인터페이스) : 클래스(인터페이스) 선언에 타입 매개변수(type parameter) 가 쓰이는 클래스(인터페이스)

제네릭 타입(generic type) : 제네릭 클래스와 제네릭 인터페이스를 통들어 이르는 말.


각각의 제네릭 타입은 일련의 매개변수화 타입(parameterized type)을 정의함.(List)

여기서 String 정규(formal)타입 매개 변수 E에 해당하는 실제(actual)타입 매개변수임.

image

제네릭 타입을 하나 정의하면 그에 딸린 로타입(raw type)도 함께 정의됨.

raw type : 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때.

예) List<E> 의 raw type 은 List

로 타입은 타입 선언에서 제네릭 타입 정보가 전부 지워진 것처럼 동작하는데, 제네릭이 도래하기 전 코드와 호환되도록하기 위한 궁여지책이라 할 수 있음.

제네릭 이전의 컬렉션

  // Stamp 인스턴스만 취급하는 컬렉션
  private final Collection stamps = ...;

실수로 Stamp 대신 Coin 을 넣더라고 아무 오류없이 컴파일 됨.(애매한 경고메시지는 줄 수도 있음)

하지만 꺼내서 사용할때 ClassCastException이 발생함.
=> 즉 런타임 때 오류가 발생하니 오류의 원인이 되는 부분을 찾기위해 코드를 전부 훑어 볼 수도 있음.

제네릭 컬렉션

  private final Collection<Stamp> stamps = ...;

위처럼 선언하면 다른 타입의 클래스를 추가하는 시점이 있다면 컴파일시 오류가 남.

컴파일러가 원소를 꺼낼 때 보이지 않는 형변환을 추가하여 절대 실패하지 않음을 보장.

로타입 사용의 문제점

제네릭이 안겨주는 안전성과 표현력을 모두 일게 됨.

하지만 그럼에도 로타입이 남아 있는 이유는 기존에 짜여져 있던 코드들과의 호환성 때문임(제네릭을 받아들이기까지 10년이 걸림).



로타입은 안되나 List<Object>는 괜찮음.

=> 제네릭의 하위타입 규칙때문에 List<String>은 List의 하위 타입이지만, List<Object>의 하위타입은 아님.

예시1) 로타입으로 매개변수를 받았을때

image

image

컴파일 가능하고 동작은 하나 실제 타입이 아닌 다른 타입의 객체를 꺼내 사용할때 ClassCastException 이 발생

예시2) 다른 매개변수 타입을 사용했을때
image

컴파일조차 안됨.

비한정 와일드카드 타입(unbounded wildcard type)

원소타입을 몰라도 되는 로 타입을 쓰고 싶다면 비한정 와일드카드를 사용하자.

비한정 와일드카드란 Set<?>와 같이 제네릭에 ?를 사용하는 것임.

제네릭은 사용하고 싶지만 타입 매개변수를 신경쓰고 싶지 않을때 사용할 수 있다.

  • 비한정 와일드카드와 로타입의 차이

    비한정 와일드카드는 안전하지만 로타입은 안전하지 않음

    => 로 타입은 아무 원소나 넣을 수 있지만 비한정 와일드카드는 null 외에는 아무것도 넣을 수 없다.

로타입 사용 허용예시

  • class 리터럴에는 써야함

    class 리터럴에는 매개변수화 타입을 사용하지 못하게 해놨음.

    List.class, String[].class, int.class 는 허용(배열과 기본타입 허용) but List<String>.class와 List<?>.class 는 허용X
  • instanceof 연산자 때는 허용

    런타임에는 제네릭 타입 정보가 지워지므로 instanceof 연산자는 비한정 와일드카드 타입 이외의 매개변수화 타입에는 적용할 수 없음.
    if( o instanceof Set){
      Set<?> s = (Set<?>)o;
      ...
    }
    
    비한정 와일드카드는 꺾쇠 때문에 코드가 지저분해지니 instanceof 때는 로타입이 나음.

용어 정리

한글 용어 영문 용어 아이템
매개변수화 타입 parameterized type List<String> 26
실제 타입 매개변수 actual type parameter String 26
제네릭 타입 generic type List<E> 26,29
정규 타입 매개변수 formal type parameter E 26
비한정 와일드카드 타입 unbounded wildcard type List<?> 26
로 타입 raw type List 26
한정적 타입 매개변수 bounded type parameter <E extends Number> 29
재귀적 타입 한정 recursive type bound <T extends Comparable<T>> 30
한정적 와일드 카드 bounded wildcard type List<? extends NUmber> 31
제네릭 메서드 generic method static <E> List<E> asList(E[] a) 30
타입 토큰 type token String.class 33

GenericRepository

기능과 구현내용은 같은데 엔티티만 달라지는 경우

변경 전

image

image



변경 후

image

image

image

728x90
반응형