Effective Java: 제네릭

Developer:Bird·2021년 11월 8일
0

이펙티브자바

목록 보기
1/1

1. 로 타입은 사용하지 마라

로 타입 사용하게 되면 개발자가 원하지 않는 인스턴스 타입이 들어간다고 해도 컴파일 시점에 잡아 낼 수 없게 된다. 따라서 항상 명시적으로 선언을 해서 컴파일 시점에 오류를 잡아내게 하는게 좋다.

로 타입 사용의 잘못된 예1)

(X) private final List<Object> stamps = ...; 
(X) private final List<> stamps = ...; 
(O) private final List<Stamp> stamps = ...;

로 타입 사용의 잘못된 예 2)

## 모르는 타입의 원소도 로 타입으로 받을 수 있도로 설정
static int numElementsInCommon(Set s1, Set s2){ 
	int result = 0;
    for (Object o1 : s1)
    	if (s2.contains(01))
        	result++;
        return result; 
}

## 모르는 타입의 경우 와일드카드 타입으로 받도록 설정
static int numElementsInCommon(Set<?> s1, Set<?> s2){
	int result = 0;
    for (Object o1 : s1)
    	if (s2.contains(01))
        	result++;
        return result; 
}

예 2) 의 와일드 카드방식으로 구현하게 되면 로 타입을 이용할 때처럼 유연한 장점을 가지고 있으며 데이터 삽입시 제한이 있어서 (null을 제외한 어떤 원소도 넣을 수 없다.) 안전하다.

로 타일을 사용해야하는 경우는 class literal을 선언사용할때 사용해야하며, 제네릭 타입에 insanceof를 사용하는 경우다.

로 타입 사용의 올바른 예)

## class literal선언
(O)
List.class,
String[] class,
int.class

(X)
List<String>.class
List<?>.class

## instanceof 사용후 형변환
if(o instanceof Set){
	Set<?> s =(Set<?>) o;
    ...
}

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

2. 배열보다는 리스트를 사용하자

배열은 공변(Covariant)이며, 리스트는 불공변(Invariant)인 차이점이 있다. 이는 자신의 상속관계에 있는 타입으로 타입캐스팅 가능한지, 없는지를 뜻한다.
예)

(X) List <Object>[] stringList = new List<String>[10]; 
(O) Object[] objects = new Long[10]

stringList의 경우 불변이기에 컴파일 오류가 생기고 objects의 경우에는 문제가 없을것이다. 다음은 배열의 방식으로 구현했을때 생길 수 있는 심각한 문제이다.

Object[] objects = new Long[10]
objects[0] = "타입이 다릅니다."

위 방식같이 구현하게 되면 컴파일 시점에는 알 수 없고, 런타임시에만 알 수 있다. 문법상 Object에 String type을 삽입할 수 있기 때문이다. 따라서 타입에 안정성이 있는

profile
끈임없이 발전하자.

0개의 댓글