class RawCollection {
private final Collection stamps = null; // 편의상 null을 할당했다.
void sample() {
stamps.add(new Coin()); // "unchecked call" 경고를 내뱉는다.
}
private static class Coin {
// ...
}
}
class RawIterator {
private final Collection stamps = null; // 편의상 null을 할당했다.
void sample() {
for (Iterator i = stamps.iterator(); i.hasNext(); ) {
Stamp stamp = (Stamp) i.next(); // ClassCastException을 던진다.
stamp.cancel();
}
}
private static class Stamp {
public void cancel() {
// ...
}
}
}
class ParameterizedCollectionSample {
private final Collection<Stamp> stamps = null;
}
List<Object>
처럼 임의 객체를 허용하는 매개변수화 타입은 괜찮다.List<Object>
는 모든 타입을 허용한다는 의사를 컴파일러에 명확히 전달한 것이다.List<Object>
를 받는 메서드에는 넘길 수 없다.List<String>
은 로 타입인 List의 하위 타입이지만, List<Object>
의 하위 타입은 아니다.List<Object>
같은 매개변수화 타입을 사용할 때와 달리 List 같은 로 타입을 사용하면 타입 안정성을 잃게 된다.class FailWithRawType {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
unsafeAdd(strings, Integer.valueOf(42));
String s = strings.get(0); // 컴파일러가 자동으로 형변환 코드를 넣어준다.
}
private static void unsafeAdd(List list, Object o) {
list.add(o);
}
}
참고로, 아래는 컴파일러가 만들어준 코드다. 생성자와 strings.get(0)을 (String) 으로 형변환하는 코드가 추가되었다.
class FailWithRawType {
FailWithRawType() {
}
public static void main(String[] args) {
List<String> strings = new ArrayList();
unsafeAdd(strings, 42);
String s = (String) strings.get(0);
}
private static void unsafeAdd(List list, Object o) {
list.add(o);
}
}
class UseUnknownElementRawTypeSample {
static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o1 : s1) {
if (s2.contains(o1)) {
result++;
}
}
return result;
}
}
class UseUnknownElementRawTypeSample {
static int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o1 : s1) {
if (s2.contains(o1)) {
result++;
}
}
return result;
}
}
로 타입을 쓰지 말라는 규칙에도 소소한 예외가 있다.
if (o instanceof Set) {
Set<?> s = (Set<?>) o;
// ...
}
한글 용어 | 영문 용어 | 예 |
---|---|---|
매개변수화 타입 | parameterized type | List<String> |
실제 타입 매개변수 | actual type parameter | String |
제네릭 타입 | generic type | List<E> |
정규 타입 매개변수 | formal type parameter | E |
비한정적 와일드카드 타입 | unbounded wildcard typ | List<?> |
로 타입 | raw type | List |
한정적 타입 매개변수 | bounded type parameter | <E extends Number> |
재귀적 타입 한정 | recursive type bound | <T extends Comparable<T>> |
한정적 와일드카드 타입 | bounded wildcard type | List<? extends Number> |
제네릭 메서드 | generic method | static <E> List<E> asList(E[] a) |
타입 토큰 | type token | String.class |
Set<Object>
는 어떤 타입의 객체도 저장할 수 있는 매개변수화 타입이고, Set<?>
는 모종의 타입 객체만 저장할 수 있는 와일드카드 타입이다.Set<Object>
와 Set<?>
은 안전하지만, 로 타입인 Set은 안전하지 않다.