-
이펙티브 자바 Item 33 - 타입 안전 이종 컨테이너를 고려하라언어/Effective Java 2024. 6. 5. 11:42
타입 안전 이종 컨테이너 패턴
컨테이너 대신 키를 매개변수화한 다음, 컨테이너에 값을 넣거나 뺄 때 매개변수화 키를 함께 제공하면 제네릭 타입 시스템이 값의 타입이 키와 같음을 보장해준다.
이러한 설계 방식을 타입 안전 이종 컨테이너 패턴이라 한다.
public class Favorites { public <T> void putFavorite(Class<T> type, T instance); public <T> T getFavorite(Class<T> type); } ... // 코드생략 public static void main(String[] args) { Favorites favorites = new Favorites(); favorites.putFavorite(String.class,"morning"); favorites.putFavorite(Integer.class, 0xcafebabe); favorites.putFavorite(Class.class, Favorites.class); String favoriteString = favorites.getFavorite(String.class); Integer favoriteInteger = favorites.getFavorite(Integer.class); Class<?> favoriteClass = favorites.getFavorite(Class.class); System.out.printf("%s %x %s", 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); } // 클래스의 리터럴 타입은 Class가 아니라 Class<T>이다. public <T> T getFavorite(Class<T> type){ return type.cast(favorites.get(type)); // Object 타입의 객체(favorites.get(type)를 꺼내 T로 바꿔 반환해야 한다. // cast메서드로 이 객체 참조를 Class 객체가 가리키는 타입으로 동적 형변환 한다. } //type 정보로 값을 get하고 이를 다시 type.case해서 return }
public static void main(String[] args) { Favorites favorites = new Favorites(); favorites.putFavorite(String.class,"morning"); // String의 클래스 타입은 Class<String>이다. favorites.putFavorite(Integer.class, 0xcafebabe); // Integer의 클래스 타입은 Class<Integer>이다. favorites.putFavorite(Class.class, Favorites.class); String favoriteString = favorites.getFavorite(String.class); Integer favoriteInteger = favorites.getFavorite(Integer.class); Class<?> favoriteClass = favorites.getFavorite(Class.class); System.out.printf("%s %x %s", favoriteString, favoriteInteger, favoriteClass.getName()); }
- Favorites 인스턴스 타입 안전하다. String타입을 요청했는데 Integer를 반환하는 일은 절대 없다!
- 모든 키의 타입이 제각각이라, 일반적인 맵과 달리 여러가지 원소를 담을 수 있다.
- 따라서 이는 안전 이종 컨테이너이다.
*컴파일 타임 타입정보와 런타임 타입 정보를 알아내기 위해 메서드들이 주고받는 class 리터럴을 타입 토큰이라고 한다.
- 핵심은 cast메서드이다. cast메서드의 반환 타입은 Class 객체의 타입 매개변수와 같다. 즉, cast 메서드는 Class 클래스가 제네릭이라는 이점을 잘 활용한다.
public class Class<T> { T cast(Object object); }
'언어 > Effective Java' 카테고리의 다른 글
이펙티브 자바 Item 35 : ordinal 메서드 대신 인스턴스 필드를 사용하라 (0) 2024.06.07 이펙티브 자바 Item 34 - int 상수 대신 열거 타입을 사용하라 (0) 2024.06.05 이펙티브 자바 Item 32 - 제네릭과 가변인수를 함께 쓸 때는 신중하라 (0) 2024.06.05 이펙티브 자바 Item31 한정적 와일드 카드를 사용해 API의 유연성을 높여라 (0) 2024.06.05 이펙티브 자바 Item 30 - 이왕이면 제네릭 메서드로 만들라 (0) 2024.06.04