Item 26. 로 타입은 사용하지 말라
이번은 제네릭에 대한 설명이다. 다음과 같이 제네릭 타입을 하나 정의하면 List<E>
이와 함께 로 타입(raw type)도 같이 정의된다. 그냥 List도 같이 만들어진다는 뜻이다.
그러면 왜 만들어지는 것이고 왜 쓰면 안되는걸까?
먼저 로 타입이 만들어지는 이유를 살펴보자. 간단하게 말하면 호환성 때문이다. 제네릭이 자바에 들어오기 전 오랜 기간 제네릭 없이 짠 코드가 널리 퍼져있었기 때문에 이를 호환하기 위해 없애지 않고 추가로 생성되게 한 것이다.
그러면 왜 쓰면 안되는걸까? 아래의 예시를 살펴보자.
// Stamp 인스턴스만 취급한다.
private final Collcetion stamps = ...;
위의 코드는 따라하지 말아야한다. stamps 인스턴스만 받는 Collection을 생성해놨다. 물론 stamps 인스턴스만을 받는 다는걸 확인하려면 주석을 확인해야 한다. 만약 이 코드를 사용하고 실수로 다른 클래스의 인스턴스를 넣어도 아무 오류 없이 들어가진다.
대신 컴파일러에서 경고메시지를 보여준다.
만약 아래와 같이 Stamp 클래스가 아닌 Coin 클래스를 넣는다면
stamps.add(new Coin(...)); // "unchecked call" 경고를 내뱉는다.
컴파일시 경고만 나올 뿐이고 넣었던 동전을 꺼내려고 해야 오류(ClassCastException : 형변환 오류)가 나오는데.
for(Interator i = stamps.iterator(); i.hasNext(); ){
Stamp stamp = (Stamp) i.next(); // ClassCastException 에러
stamp.cancel();
}
오류란, 컴파일할 때 발견하는게 가장 좋다. 위의 오류는 런타임중에 발생하기 때문에 원인을 찾기 위해 모든 코드를 살펴봐야 할 수도 있게 된다.
이렇듯 그냥 raw 타입을 쓰게 되면 모든 인스턴스를 받을 수 있게 되고 실수를 하게되면 찾기 어렵다. 하지만 아래와 같이 제네릭을 쓴다면
private fianl Collection<Stamp> stamps = ...;
컴파일러에 Stamp 인스턴스만 넣어야 한다고 명시하기 때문에 다른 인스턴스가 들어가려 하면 컴파일 과정에서 에러가 발생하여 조기 수정이 가능해진다.
만약 타입 매개변수가 무엇인지 신경 쓰고 싶지 않다면 Set<?>
와 같이 비한정적 와일드카드 타입 : ? 을 사용하자. ?를 사용하면 어떤 타입이든 담을 수 있게 된다.
Author And Source
이 문제에 관하여(Item 26. 로 타입은 사용하지 말라), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@simgyuhwan/Item-26.-로-타입은-사용하지-말라저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)