5장 : 제네릭

2023. 4. 6. 12:47스터디/이펙티브 자바 스터디

728x90

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

- 로타입은 전 코드와 호환되도록 하기 위한 궁여지책

- 오류는 가능한 발생 즉시, 이상적으로는 컴파일시 발견하는 것이 좋음

- 로타입을 쓰면 제네릭이 안겨주는 안정성과 표현력 모두 잃게 됨

- List 쓸 바에 List<Object> 쓰자 : 모든 타입을 허용한다는 것을 컴파일러에게 명확히 전달

- 어떤 타입이라도 담을 수 있는 가장 벙용적인 제네릭을 만들려면 와일드카드 타입 <?> 사용

- class 리터럴에는 로 타입을 써야함

- instanceof 연산자는 비한정적 와일드카드 타입 이외의 매개변수화 타입은 적용 불가

 


아이템 27. 비검사 경고를 제거하라 


아이템 28. 배열보다는 리스트를 사용하라 

공변 : Sub가 Super의 하위 타입이면 배열 Sub[] 는 Super[]의 하위 타입불공변 : Sub가 Super의 하위 타입이면 리스트 List<Sub> 는 List<Super>의 하위 타입이 아님- 제네릭은 타입 정보가 런타임에는 소거됨. 원소 타입을 컴파일 타임에만 검사하며 런타임에는 알수조차 없음- 제네릭은 타입 안전하지 않기 때문에 배열 생성을 허용하지 않음- 실체화 될 수 있는 타입은 비한정적 와일드카드뿐 


아이템 29. 이왕이면 제네릭 타입으로 만들라 

아이템 30. 이왕이면 제네릭 메서드로 만들라 

- 타입 매개변수 목록은메서드의 제한자와 반환  타입 사이에 옴


아이템 31. 한정적 와일드카드를 사용해 API 유연성을 높이라 

- Collection<? super E>  : E의 상위타입의 Collection이어야한다

- 유연성을 극대화하려면 원소의 생산자나 소비자용 입력 매개변수에 와일드카드 타입을 사용해야

- 입력 매개변수가 생산자와 소비자 역할을 동시에 한다면 와일드카드 타입을 써도 좋을 것이 없음

- PECS : producer - extends, consumer - super

- 매개변수화 타입 T가 생산자라면 <? extends T> 사용, 소비자라면 <? super T> 사용

- 반환 타입에는 한정적 와일드카드 타입을 사용하면 안 됨 

- 메서드 선언에 타입 매개변수가 한 번만 나오면 와일드카드로 대체 


아이템 32. 제네릭과 가변인수를 함께 쓸 때는 신중하라 

타입 안전성이 깨지니 제네릭 varargs 배열 매개변수에 값을 저장하는 것은 안전하지 않음- 아무것도 저장하지 않고, 덮어쓰지 않고, 밖으로 노출되지 않는다면 타입 안전- 순수하게 인수들을 전달하는 일만 하면 그 매서드은 안전- 제네릭 varargs 매개변수 배열에 다른 메서드가 접근하도록 허용하면 안전하지 않음.- 일부 함수를 호출만 하는 일반 메서드에 넘기는 것도 안전- 가변 인수와 제네릭은 궁합이 좋지 않음

 

아이템 33. 타입 안전 이종 컨테이너를 고려하라 

- 제네릭에서 매개변수화 되는 대상은 컨테이너 자신

- 타입 안전 이종 컨테이너 : 키를 매개변수화한 다음 컨테이너에 값을 넣거나 뺄 때 매개변수화한 키를 함께 제공

 

public class Favorites {
    // 코드 33-3 타입 안전 이종 컨테이너 패턴 - 구현 (200쪽)
    private Map<Class<?>, Object> favorites = new HashMap<>();

    public <T> void putFavorite(Class<T> type, T instance) {
        favorites.put(Objects.requireNonNull(type), instance);
    }

    public <T> T getFavorite(Class<T> type) {
        return type.cast(favorites.get(type));
    }

//    // 코드 33-4 동적 형변환으로 런타임 타입 안전성 확보 (202쪽)
//    public <T> void putFavorite(Class<T> type, T instance) {
//        favorites.put(Objects.requireNonNull(type), type.cast(instance));
//    }

    // 코드 33-2 타입 안전 이종 컨테이너 패턴 - 클라이언트 (199쪽)
    public static void main(String[] args) {
        Favorites f = new Favorites();
        
        f.putFavorite(String.class, "Java");
        f.putFavorite(Integer.class, 0xcafebabe);
        f.putFavorite(Class.class, Favorites.class);
       
        String favoriteString = f.getFavorite(String.class);
        int favoriteInteger = f.getFavorite(Integer.class);
        Class<?> favoriteClass = f.getFavorite(Class.class);
        
        System.out.printf("%s %x %s%n", favoriteString,
                favoriteInteger, favoriteClass.getName());
    }
}
728x90