[Effective Java] 5 - item 26 로 타입은 사용하지 말라.
item 26 로 타입은 사용하지 말라.
Raw type
로 타입이란, List list
와 같이 제너릭 클래스 혹은 인터페이스(=제너릭 타입)를 사용할 때 타입 매개변수를 전혀 사용하지 않는 것을 의미한다.
제너릭 도입(Java 5) 이전 코드와의 호환성을 위해 사용하였지만, 되도록 사용하지 않는 것을 권장한다.
제너릭 타입
제너릭 타입은 매개변수화 타입을 정의한다.
- 먼저 클래스 혹은 인스턴스의 이름이 나오고,
- 이어서 꺾쇠괄호 안에 실제 타입 매개변수를 나열한다.
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