이펙티브 자바 아이템33

한주영·2024년 1월 25일
0

이펙티브자바

목록 보기
25/33

타입 안전 이종 컨테이너를 고려하라

제네릭은 Set< E >, Map<K, V>등의 컬렉션과 ThreadLocal< T >, AtomicReference< T > 등 단일원소 컨테이너에서도 쓰인다

매개변수화 되는 대상은 컨테이너 자신이다.

예로 Set에는 원소의 타입을 뜻하는 하나의 매개변수만 있으면 되고
Map에는 키와 값의 타입을 뜻하는 2개만필요하다,

타입 안전 이종 컨테이너

컨테이너 대신 키를 매개변수화 한 다음 컨테이너에 값을 넣거나 뺄때 매개변수화한 키를 함께 제공

간단한 예
타입별로 즐겨 찾는 인스턴스를 저장하고 검색할수 있는 Favorites클래스를 정의

public class Favorites {
    
    public <T> void putFavorite(Class<T> type, T instance);
    public <T> getFavorite(Class<T> type);
}

타입 안전 이종 컨테이너 패턴-클라이언트
String,Integer,Class 인스턴스를 저장,검색,출력하는 코드

   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.println("%s %x %s%n", favoriteString,favoriteInteger,favoriteClass.getName());
    }

구현된 타입 안전 이종 컨테이너

public class Favorites {

    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))  ; 
    }
}

1) private 변수 타입은 Map< Class< ? >, Object>
2) 와일드카드가 중첩되있음
-> 맵이 아니라 키가 와일드 카드 타입
3) cast 메서드는 형변환 연산자의 동적버전
-> 주어진 인수가 Class객체가 알려주는 타입의 인스턴스 인지를 검사한 다음 맞다면 그 인수를 그대로 반환, 아니면 예외를 던짐

Favorites클래스에는 알아야할 2가지 제약이 있음
1) 악의적인 클라이언트가 Class객체를 로타입으로 넘기면 인스턴스 타입 안정성이 쉽게 깨진다.
->타입 불변식을 어기는 일이 없도록 보장하려면 instance타입이 type으로 명시한 타입과 같은지 확인 -> 동적 형변환 사용

2)실체화 불가 타입에는 사용할수없다
-> String,String[]은 저장가능, List< String >저장 불가능
클래스 객체를 얻지 못하기 때문에

한정적 타입 토큰

1)Favorites가 사용하는 타입 토큰은 비한정적이다.
2) 메서드들이 허용하는 타입을 제한하고 싶을때 한정적 타입 토큰을 활용하면된다
-> 단순히 한정적 타입 매개변수나 한정적 와일드 카드를 사용하여 표현 가능한 타입을 제한하는 타입 토큰

3)한정적 타입토큰을 안전하게 형변환 해주는 메서드
-> asSubClass 메서드

핵심정리

1) 제네릭 형태에서는 한 컨테이너가 다룰수있는 타입 매개변수의 수가 고정
2) 컨테이너 자체가 아닌 키를 타입 매개변수로 비꾸면 제약이 없는 타입 안전 이종 컨테이너를 만들수있다.
3) 타입 안전 이종 컨테이너는 Class를 키로 쓰며, 이런식으로 쓰이는 Class객체를 타입 토큰 이라고 한다.

profile
백엔드개발자가 되고싶은 코린이:)

0개의 댓글

Powered by GraphCDN, the GraphQL CDN