제너릭 타입을 사용한다면 로 타입은 사용하지 말자
•
클래스와 인터페이스 선언에 타입 매개 변수를 사용하는 제네릭 클래스 혹은 제네릭 인터페이스를 통틀어 제네릭 타입이라고 한다.
•
각 제네릭 타입은 매개변수화 타입을 정의하는데, List<String>의 경우에는 타입이 String인 리스트를 뜻하는 매개변수화 타입이다.
•
List<E>의 제네릭 타입을 List의 로 타입 형태로 사용할 수 있는데, 로 타입은 타입 선언에서 제네릭 타입 정보가 전부 지워진 것처럼 동작한다.
•
이런 로 타입은 제네릭이 도입되기 전의 코드들과의 호환성을 위해 존재하지만, 로 타입을 사용하면 선언과 다른 타입의 변수를 넣어도 컴파일되고 실행되기 때문에 가급적 사용하지 않는 것이 좋다.
•
오류는 컴파일 시에 발견되는 것이 바람직한데, 위와 같이 로 타입을 사용하게 되면 컴파일 시에는 오류를 잡지 못하고 런타임 중에 오류가 발생하게 된다.
•
로 타입 대신 제네릭 타입을 사용하면 제네릭으로 선언된 변수에는 선언에 맞는 타입의 인스턴스만을 넣어야 함을 컴파일러가 인지할 수 있고, 컴파일러에서 어떤 부분이 어떻게 잘못 되었는지를 짚어준다.
•
타입 안전성과 디버깅의 용이성, 표현력을 위해 가급적 로 타입 대신 제네릭 타입을 사용하자. 로 타입은 과거 버전의 호환성이 필요한 경우에만 사용하자
Object 타입과 와일드 카드
•
List와 같은 로 타입은 사용하면 안되지만, List<Object>처럼 임의의 객체를 허용하는 매개변수화 타입은 괜찮다.
•
List의 경우에는 무슨 일이 일어나든 상관하지 않겠다는 의미이고, List<Object>는 모든 타입을 허용하겠다고 컴파일러에 알려주는 의미이다.
•
제네릭 타입을 사용할 때 실제 타입 매개변수가 무엇인지 신경 쓰고 싶지 않다면 List<?>와 같은 와일드 카드를 사용하자.
•
실제 List<?>에는 어떤 원소도 넣을 수 없는데, List<? extends T>와 같이 한정적 와일드 카드 타입을 선언하여 사용하는 것이 좋다.
예외적 상황에는 로 타입으로 사용해야한다
•
class 리터럴에는 매개변수화 타입을 사용할 수 없다.
List.class // 허용 O
String[].class // 허용 O
Int.class // 허용 O
List<?>.class // 허용 X
Java
복사
•
instanceof 연산자에는 제네릭 타입 정보가 지워지므로 비한정적 와일드카드 타입(List<?>) 이외의 매개변수화 타입은 적용할 수 없다.
•
로 타입이나 제네릭 타입이나 동일하게 동작하기 때문에, 코드를 간략하게 하기 위해 로타입을 사용하자
if (o instanceof Set) {
Set<?> s = (Set<?>) o;
...
}
Java
복사