[Effective Java] 아이템 26. 로 타입은 사용하지 말라

2022. 10. 6. 23:49· BE/Java
목차
  1. 아이템 26. 로 타입은 사용하지 말라
반응형

EFFECTIVE JAVA(이펙티브 자바)


 

이 포스팅에서 작성하는 내용은 EFFECTIVE JAVA(이펙티브자바) 에서 발췌하였습니다.


아이템 26. 로 타입은 사용하지 말라

관련 용어 모음집

한글 용어 영문 용어 예 아이템
매개변수화 타입 parameterized type List<String> 아이템26
실제 타입 매개변수 actual type parameter String 아이템26
제네릭 타입 generic type List<E> 아이템26, 29
정규 타입 매개변수 formal type parameter E 아이템26
비한정적 와일드카드 타입 unbounded wildcard type List<?> 아이템26
로 타입 raw type List 아이템26
한정적 타입 매개변수 bounded type parameter <E extends Number> 아이템29
재귀적 타입 한정 recursive type bound <T extends Comparable<T>> 아이템30
한정적 와일드카드 타입 bounded wildcard type List<? extends Number> 아이템31
제네릭 메서드 generic method static <E>
List<E>
asList(E[] a)
아이템30
타입 토큰 type token String.class 아이템33

 

제네릭 타입

  • 클래스와 인터페이스 선언에 타입 매개변수가 쓰이는 것
    • 예시로, List 인터페이스는 원소의 타입을 나타내는 타입 매개변수 E를 받는다.
    • 그래서 이 인터페이스의 완전한 이름은 List<E>지만, 짧게 그냥 List라고도 자주 씀
  • 제네릭 클래스와 제네릭 인터페이스를 통틀어 제네릭 타입이라 함.
  • 각각의 제네릭 타입은 일련의 매개변수화 타입을 정의한다.
    • ex) List<String>은 원소의 타입인 String인 리스트를 뜻하는 매개변수화 타입이다.
    • 여기서 String이 정규 타입 매개변수 E에 해당하는 실제 타입 매개변수다.

 

 

로 타입(raw type)

  • 제네릭 타입을 하나 정의하면 그에 딸린 로 타입(raw type)도 함께 정의된다.
  • raw type? 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때를 말함
  • ex) List<E>의 raw type은 List 다.
  • 로 타입을 쓰는 걸 언어 차원에서 막아두진 않았지만, 절대로 사용하면 안된다.
  • 로 타입을 쓰면 제네릭이 안겨주는 안전성과 표현력을 모두 잃게 됨
  • 이 기능은 왜 있는걸까? 제네릭이 사용되기 이전 코드와 호환되기 위한 기능.
  • List 같은 로 타입은 사용해서는 안되지만, List<Object> 처럼 임의 객체를 허용하는 매개변수화는 괜찮다. (ex 2 소스)
    • List는 제네릭 타입에서 완전히 발을 뺀 것이고, List<Object>는 모든 타입을 허용한다는 의사를 컴파일러에 명시한 것
    • List에는 List<String>을 넘길 수 있지만, List<Object>를 받는 메서드에는 넘길 수 없음
    • 제네릭의 하위 타입 규칙 때문.
      즉, List<String>은 로 타입인 List의 하위 타입이지만, List<Object>의 하위타입이 아님
  • List<Object> 같은 배개변수화 타입을 사용할 때와 달리 List 같은 로 타입을 사용하면 타입 안정성을 잃게된 다.

 

ex 1-1) raw type 예제

// stamps는 Stamp Instance만 넣을 수 있다고 가정하자.
private final Collection stamps = ...;

// 이렇게 Coin Instance를 넣으면, 오류없이 컴파일되고 실행됨.
stamps.add(new Coin(...)); // unchecked call "경고"를 뱉음

for(Iterator i = stamps.iterator(); i.hasNext() ; ) {
    // ClassCastException 발생(위에 넣은 Coin Instance를 Stamp로 변환하려고 해서)
    Stamp stamp = (Stamp) i.next();	
    
    stamp.cancel();
}
  • Coin Instance를 넣을 때는 오류가 안나지만, 실제로 꺼내서 사용하면 오류가 발생한다.
  • 오류는 가능한 한 발생 즉시, 이상적으로는 컴파일할 때 발견하는 것이 좋다.

 

ex 1-2) 매개변수화된 컬렉션 타입 (타입 안정성이 확보)

// stamps는 Stamp Instance만 넣을 수 있다고 컴파일러에게 알려줌
private final Collection<Stamp> stamps = ...;

// stamps에 Coin Instance를 넣으면 경고가 아닌 컴파일 오류가 발생함
stamps.add(new Coin(...));

 

 

 

ex 2-1) raw type 예제(List 로 받는 경우)

public static void main(String[] args) {
    List<String> strings = new ArrayList<>();
   
    unsafeAdd(strings, Integer.valueOf(42));
    
    // 컴파일은 정상작동하지만, ClassCastException이 발생(Integer를 String으로 변환하려함)
    String s = strings.get(0);	// 컴파일러가 자동으로 형변환 코드를 넣어줌
}

// raw type인 List 이용
private static void unsafeAdd(List list, Object o) {
    list.add(o);
}

 

ex 2-2) List<Object> 로 받는 경우

public static void main(String[] args) {
    List<String> strings = new ArrayList<>();
   
    unsafeAdd(strings, Integer.valueOf(42));
    
    // 컴파일조차 안 됨
    String s = strings.get(0);	// 컴파일러가 자동으로 형변환 코드를 넣어줌
}

// raw type인 List 이용
private static void unsafeAdd(List<Object> list, Object o) {
    list.add(o);
}

 

 

원소의 타입을 몰라도 되는 로 타입을 사용하는 방법

2개의 집합(Set)을 받아 공통 원소를 반환하는 메서드

 

ex 3-1) 로 타입 이용(잘못된 예)

static int numElementsInCommon(Set s1, Set s2) { 
    int result = 0;
    for (Object o : s1)
        if (s2.contains(o1))
            result++;
    
    return result;
}
  • 이 메서드는 동작하지만, 로 타입을 사용해 안전하지 않다.
  • 이 경우에는 비한정적 와일드카드 타입을 사용하는 것이 좋다.
  • 제네릭 타입을 쓰고 싶지만 실제 타입 매개변수가 무엇인지 신경쓰고 싶지 않다면 ?를 사용하면 좋다.

 

ex 3-2) 비한정적 와일드카드 타입 사용

static int numElementsInCommon(Set<?> s1, Set<?> s2) {

 

 

 

로 타입을 사용하는 예외 상황

  • class 리터럴에는 로 타입을 써야 한다.
    • 자바 명세는 class 리터럴에 매개변수화 타입을 사용하지 못하게 함(배열과 기본타입은 허용)
      List.class, String[].class, int.class는 허용하지만, List<String>.class와 List<?>.class는 허용 안함
  • 런타임시에는 제네릭 정보가 지워지므로 instanceof 연산자는 비한정적 와일드카드 타입 이외의 매개변수화 타입에는 적용할 수 없다
    • 로 타입이든 비한정적 와일드카드 타입이든 instanceof 는 똑같이 동작한다.
    • 비한정적 와일드카드 타입의 꺾쇠괄호와 물음표는 아무런 역할 없이 코드만 지저분하게 만드므로, 로 타입만 사용하는 것이 깔끔하다.

 

ex 4) raw type을 사용한 좋은 예 (instanceof 연산자)

if (o instanceof Set) {    // 로 타입
    Set<?> s = (Set<?>) o; // 와일드카드 타입
}

o의 타입이 Set임을 확인한 다음, 와일드카드 타입인 Set<?>로 형변환해야한다.

 

 

 

 

정리

  • raw type을 사용하면 런타임에 예외가 발생할 수 있으니 사용하지 말자
  • raw type은 제네릭이 도입되기 전 코드와의 호환성을 위해 제공된다.
  • Set<Object>는 어떤 타입의 객체도 저장할 수 있는 매개변수화 타입
  • Set<?>는 모종의 타입 객체만 저장할 수 있는 와일드카드 타입
  • 이들의 raw type인 Set은 제네릭 타입 시스템에 속하지 않는다.
  • Set<Object>, Set<?>는 안전하지만, raw type인 Set은 안전하지 않다.
반응형

'BE > Java' 카테고리의 다른 글

[Effective Java] 아이템 28. 배열보다는 리스트를 사용하라  (0) 2022.10.11
[Effective Java] 아이템 27. 비검사 경고를 제거하라  (0) 2022.10.07
[Effective Java] 아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라  (0) 2022.10.05
[Effective Java] 아이템 24. 멤버 클래스는 되도록 static으로 만들라  (0) 2022.10.04
[Effective Java] 아이템 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라  (1) 2022.09.30
  1. 아이템 26. 로 타입은 사용하지 말라
'BE/Java' 카테고리의 다른 글
  • [Effective Java] 아이템 28. 배열보다는 리스트를 사용하라
  • [Effective Java] 아이템 27. 비검사 경고를 제거하라
  • [Effective Java] 아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라
  • [Effective Java] 아이템 24. 멤버 클래스는 되도록 static으로 만들라
멍목
멍목
개발 관련 새롭게 알게 된 지식이나 좋은 정보들을 메모하는 공간입니다.
반응형
멍목
김멍목의 개발블로그
멍목
전체
오늘
어제
  • 분류 전체보기 (514)
    • BE (190)
      • Spring (21)
      • Java (141)
      • Kotlin (6)
      • JPA (22)
    • FE (33)
      • Javascript (16)
      • Typescript (0)
      • React (5)
      • Vue.js (9)
      • JSP & JSTL (3)
    • DB (32)
      • Oracle (22)
      • MongoDB (10)
    • Algorithm (195)
    • Linux (8)
    • Git (6)
    • etc (42)
    • ---------------------------.. (0)
    • 회계 (4)
      • 전산회계 2급 (4)
    • 잡동사니 (2)

블로그 메뉴

  • 홈
  • 관리

공지사항

인기 글

태그

  • 자바공부
  • 코테 공부
  • vue3 공부
  • MongoDB 기초부터 실무까지
  • java 8
  • JPA
  • 프로젝트로 배우는 Vue.js 3
  • 전산회계 2급 준비
  • JPA 공부
  • 코틀린
  • Effective Java
  • 이펙티브자바
  • 자바 개발자를 위한 코틀린 입문
  • 자기공부
  • 코테공부
  • MongoDB with Node.js
  • junit5
  • 자바 공부
  • 알고리즘공부
  • Java to Kotlin
  • MongoDB 공부
  • 이펙티브 자바
  • 더 자바 애플리케이션을 테스트하는 다양한 방법
  • 자기 공부
  • 더 자바 Java 8
  • 자바 테스팅 프레임워크
  • 알고리즘 공부
  • 자기 개발
  • Oracle
  • 자기개발

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.0
멍목
[Effective Java] 아이템 26. 로 타입은 사용하지 말라
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.