Item26 - 로 타입은 사용하지 말라
2023. 12. 4. 23:13ㆍBook/이펙티브 자바
- 런타임이 아닌 컴파일 타임에 문제를 찾을 수 있다.(안전성)
- 제네릭을 활용하면 이 정보가 주석이 아닌 타입 선언 자체에 녹아든다(표현력)
public static void main(String[] args) {
//Generic 사용전
List numbers = new ArrayList();
numbers.add(10);
numbers.add("son");
for (Object number : numbers) {
System.out.println((Integer) number); => 런타임 에러
}
//Generic 등장 후
List<Integer> numberss = new ArrayList<>();
numberss.add(10);
numberss.add("son"); => 컴파일 에러
for (Object number : numberss) {
System.out.println((Integer) number);
}
}
- 그렇다면 자바는 "로 타입"을 왜 지원하는가?
=> 제네릭이 없었던 이전 버번의 하위호환성 때문에
- List 같은 로 타입은 사용해선 안 되나, List<Object>처럼 임의 객체를 허용하는 매개변수화 타입은 괜찮다. 둘의 차이점이 뭘까?
=> 매개변수로 List를 받는 메서드에 List<String>을 넘길 수 있지만, List<Object>를 매개변수로 받는 메서드에는 넘길 수 없다. 이는 제네릭의 하위 타입 규칙 때문인데 아이템 28에서 자세하게 배울 것이다.
- 로 타입을 쓴 메서드에는 어떤 문제가 있을까?
static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
s1.add(1);
for (Object o1 : s1) {
if(s2.contains(o1)) {
result++;
}
}
return result;
}
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
System.out.println(Numbers.numElementsInCommon(set, Set.of(1, 2)));
}
=> 이 메서드는 동작은 하지만 로 타입을 사용해 안전하지 않다. 불변식을 훼손하기 쉽기 때문이다. 예를 들면 numElementsInCommon 메서드의 첫 번재 매개변수 s1.add(1)을 하면 작동한다.
반면 Set에 비한정적 와일드카드 타입을 사용하면 s1.add(1)은 에러를 뱉는다.
static int numElementsInCommon(Set<?> s1, Set s2) {
int result = 0;
s1.add(1);
for (Object o1 : s1) {
if(s2.contains(o1)) {
result++;
}
}
return result;
}
'Book > 이펙티브 자바' 카테고리의 다른 글
Item28 - 배열보다는 리스트를 사용하라 (2) | 2023.12.05 |
---|---|
Item27 - 비검사 경고를 제거하라 (2) | 2023.12.05 |
Item25 - 톱레벨 클래스는 한 파일에 하나만 담으라 (1) | 2023.12.03 |
Item24 - 멤버 클래스는 되도록 static으로 만들라 (1) | 2023.12.03 |
Item23 - 태그 달린 클래스보다는 클래스 계층 구조를 활용하라 (0) | 2023.12.03 |