개발 일지

Item 26. 로 타입은사용하지 말라 본문

카테고리 없음

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

junjun_ 2023. 2. 22. 21:14
로 타임을 사용하면 런타임에 예외가 일어날 수 있으니 사용하면 안 된다.
로타입은 제네릭이 도입되기 이전 코드와의 호환성을 위해 제공될 뿐이다. 

 

제네릭 타입이란

  • 클래스, 제네릭 인터페이스를 통틀어 일컫는 말. 
  • 인터페이스 선언에 타입 매개변수가 쓰이는 것을 말함.
  • List <E>

 로(raw) 타입이란

  • 매개변수 가 없는 제네릭 타입
  • 예. List<E>에서 로타입은 List이다.

 

로 타입(raw type)의 문제점 

 

로타입을 쓰면 컴파일 타임에 타입 정보를 알지 못한다.

오류는 가능한 발생 즉시, 이상적으로는 컴파일할 때 발견하는 게 좋다. 그러나 로 타입을 사용하면 컴파일 시점이 아닌  런타임에 오류를 알아챌 수 있다. 

 

ex) 제네릭 타입이 지원 전 raw타입 사용

// Stamp 인스턴스만 취급한다.
private final Collection stamps = ...;
// 실수로 동전을 넣는다.
stamps.add(new Coin(...));   // "unchecked call" 경고를 내뱉는다.

 

  • 실수로 다른 타입의 객체를 넣어도 오류 없이 컴파일되고 실행됨

 

for (Iterator i = stamps.iterator(); i.hasNext(); ) {
// 인스턴스가 스탬프가아닌 코인이기 때문에 ClassCastException을 던진다.
    Stamp stamp = (Stamp) i.next();    
    
    stamp.cancel();
}
  • 컬랙션에서 이 동전을 다시 꺼내기 전에는 오류를 알아채지 못한다. 

 

But 제네릭을 활용하여 이렇게 선언하면 

private final Collection<Stamp> stamps = ...;
  • 컴파일러는 stamp에는 Stamp의 인스턴스만  넣어야 함을 인지하게 된다.
  • 똑같이 다른 타입의 인스턴스를 넣을려 하면 컴파일 오류가 발생하고 무엇이 잘못되었는지를 정확히 알려준다.

 

로(raw)타입의 대안

List<Object>처럼 임의 객체를 허용하는 매개변수화 타입

  • List는 제네릭 타입에서 완전히 발을 뺀 것이고
  • List<Object>는 모든타입울 허용한다는 의사를 명확히 전달했다.

 

비한정 와일드카드 타입

  • 비한정 와일드카드 타입은 제네릭 타입을 쓰고 싶지만, 실제 타입 매개변수가 무엇인지 신경쓰고 싶지 않을 때 사용.
  • <E>에 특정 타입이 아닌 <?>를 사용한다, 
  • Set<E>의 비한정 와일드카드 타입은 Set<?>

 

 

예외

class 리터럴에는 로타입을 사용한다.

  • 자바 명세 자체가 class 리터럴에 매개변수화 타입을 사용하지 못하게 하였다.
  • 허용: List.class, String[].class, int.class
  • 불가: List<String>.class, List<?>.class

 

instanceof 연산자는 로타입을 사용한다.

  • instanceof 연산자는 비한정 와일드카드 타입 이외의 매개변수화 타입에는 적용할 수 없다.
  • 로타입이든 비한정적 와일드타입이든 instanceof는 똑같이 동작한다.

 


 

 

정리

  • 로 타입은 결코 사용해선 안된다. 이것을 컴파일러가 허용하도록 둔 이유는 자바 1.5 버전 이전의호환성 때문이다.
  • 제너릭은 특정 파라미터 타입만을 제한한다. 따라서, 모든 파라미터 타입을 허용하도록 하고 싶다면 비한정적 와일드카드를 사용하자.