1 minute read

item 26 로 타입은 사용하지 말라.

Raw type

로 타입이란, List list와 같이 제너릭 클래스 혹은 인터페이스(=제너릭 타입)를 사용할 때 타입 매개변수를 전혀 사용하지 않는 것을 의미한다. 제너릭 도입(Java 5) 이전 코드와의 호환성을 위해 사용하였지만, 되도록 사용하지 않는 것을 권장한다.

제너릭 타입

제너릭 타입은 매개변수화 타입을 정의한다.

  1. 먼저 클래스 혹은 인스턴스의 이름이 나오고,
  2. 이어서 꺾쇠괄호 안에 실제 타입 매개변수를 나열한다.
List<String> listStr = ...;

로 타입을 사용하지 않는 이유

private final Collection stamps = ...; // Stamp 인스턴스만 취급한다.
stamps.add(new Coin(...)) 
// 실수로 Coin 인스턴스를 add()시
// "unchecked call" 경고가 발생한다.
private final Collection<Stamp> stamps = ...; // 제너릭 사용 - 매개변수화
stamps.add(new Coin(...)) 
// 이제 stamps에 다른 타입 인스턴스를 넣으면, 
// 컴파일 오류(incompatible types)가 발생하게 된다.

위의 예시 코드에서 확인할 수 있듯, 로 타입을 사용한다면 제너릭의 안정성과 표현력을 모두 잃게 된다.

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

static int numElementsInCommon(Set s1, Set s2) {    
	int result = 0;
    for (Object o1 : s1)
        if (s2.contains(o1)) result++;
    return result;
}

위 코드는 동작은 하지만, 로 타입을 사용하므로 타입 불변식을 훼손할 수 있다.

static int numElementsInCommon(Set<?> s1, Set<?> s2) {
  int result = 0;
  for (Object o1 : s1) {
    if (s1.contains(s2))
      result++;
  }
  return result;
}

와일드카드<?>를 사용하면, 실제 타입 매개변수는 무엇인지 신경쓰지 않아도 된다. 어떤 타입이라도 사용 가능한 가장 범용적인 매개변수화로 볼 수 있다. 와일드카드는 type-safe하고, 로 타입은 그렇지 않으므로 와일드카드를 사용하는 것이 좋다.

예외

  • 자바 명세에서 class 리터럴에는 매개변수화 타입을 사용하지 못하게 했다. 따라서, class 리터럴에는 로 타입을 사용해야 한다.
  • instanceOf 연산자를 사용할 때는 로 타입을 쓰는 것이 좋다.
if (o instanceof Set) {       // 로 타입
	Set<?> s = (Set<?>) o;    // 와일드카드 타입, 검사 형변환.
	...
}

Leave a comment