개발 기록

[이펙티브 자바] 아이템 26 본문

JAVA

[이펙티브 자바] 아이템 26

수염차 2024. 12. 2. 15:39

## 로 타입은 사용하지 말라

 

### 로 타입 : 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않은 것

ex) List<E>의 로 타입 : List

- 쓰면 안 되는 이유 : 오류를 컴파일할 때가 아닌 런타임시 발견할 수 있다.

ex) 실수도 Stamp 대신 Coin을 넣어도 아무 오류 없이 컴파일되고 실행됨.

// 제네릭을 지원하기 전엔 컬렉션을 아래와 같이 선언했다.
private final Collection stamps = ...;

stamps.add(new Coin(...));

for (Iterator it = stamps.iterator(); i.hasNext();) {
  Stamp stamp = (Stamp) i.next(); // ClassCastException
  stamp.cancel();
}
// 타입 안전성 확보!
private final Collection<Stamp> stamps = ...;

 

 

- 로 타입이 있는 이유 : 제네릭이 도입되기 이전 코드와의 호환성을 위해 제공.

 

### List<Object>

- 타입인 List 매개변수화 타입인 List<Object> 차이

  - List<Object>는 모든 타입을 허용한다는 의사를 컴파일러에 명확히 전달.

  - 매개변수로 List 받는 메서드에 List<String> 넘길 있지만, List<Object> 받는 메서드에는 넘길 다.

-> List<Object> 같은 매개변수화 타입을 사용할 때와 달리 List 같은 로 타입을 사용하면 타입 안전성을 잃게 된다.

 

### 비한정적 와일드카드 타입

- Set<?>

- 와일드카드 타입은 안전하고, 로 타입은 안전하지 않다.

  - 비 한정적 와일드타입에는 null 이외의 어떤 원소도 넣을수도(add) 없고, 가져와도(get) 타입을 알 수 없는 제약이 있다.

  - Object에 정의되어 있는 기능만 사용 가능.  equals(), toString(), hashCode()…

  - 이 제약에서 벗어나고 싶다면 ? extends 클래스와 같이 한정적 와일드카드 타입을 이용해 어떤 클래스의 하위 클래스를 받을 것인지 명시하면 된다.

 

 

### 로 타입을 써야 할 때

1.  class 리터럴

  - 자바 명세는 class 리터럴에 매개변수화 타입을 사용하지 못하게 했다. (배열과 기본 타입은 허용)

  - List.class, String[].class, int.class는 허용하고, List<String>.class와 List<?>.class는 허용하지 않는다.

2.  instanceof 연산자

  - 런타임에는 제네릭 타입 정보가 지워지므로 instanceof 연산자는 비한정적 와일드카드 타입 이외의 개변수화 타입에는 적용할  없다.

  - 그리고 타입이든 비한정적 와일드카드타입 이든 instanceof 완전히 똑같이 동작한다. 

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

'JAVA' 카테고리의 다른 글

[이펙티브 자바] 아이템 29  (0) 2024.12.13
[이펙티브 자바] 아이템 24  (0) 2024.11.27
[이펙티브 자바] 아이템 21,22  (0) 2024.11.19
[이펙티브 자바] 아이템 18  (0) 2024.11.04
[이펙티브 자바] 아이템 15  (0) 2024.10.29
Comments