List<String> stringList = List.of("T1","T2","T3");
static<E> List<E> of (E e1, E e2, E e3) {
return new ImmutableCollections.ListN<>(e1, e2, e3);
}
private static UnaryOperator<Object> IDENTIFY_FN = (t) -> t;
public static<T> UnaryOperator<T> identityFunction(){
return (UnaryOperator<T>) IDENTIFY_FN; (O)
return IDENTIFY_FN; (X)
//object는 제레닉으로 캐스팅죄디 않음. 유형이 다르기 때문에 에러발생
}
Method의 parameter 타입을, interface의 Type으로 한정한다.
interface Comparable<t>{
int compare(T o);
}
genric 타입과 같이 형변환 해야하는 method보다 generic method가 더 안전하고, 심지어 사용허기도 쉽다. (형변환 해야하는 메서드는 generic으로 만들자)
public class Stack<E>{
public static final int DEFAULT_SIZE = 20;
private int size;
private E[] elements;
public Stack(){ elements = (E[]) new Object[DEFAULT_SIZE]; size = 0;}
public E pusg(E item){
elements[++size] = item;
return item;
}
public void pushAll(Iterable<E> src){
for (E e : src){
push(e);
}
}
}
//컴파일 에러 : 불공변이기 때문에 (invariant) 자가 타입만 허용
Stack<Number> numberStack = new Stack<>();
Iterable<Integer> integers = List.of(1,2);
numberStack.pushAll(integers);
//제네릭 <E> 를 extends한 와일드카드로 입력
public void pushAll(Iterable<? extends E> src){
for (E e: src)
push(e);
}
Mehtod의 arguments의 개수를 클라이언트가 조절할 수있게 한다.
또한 반드시 한 개의 가변 인수만을 사용해야 하며 맨 마지막 Arguments로 사용해야 한다.
static void mergeAll(List<String>.. stringList){}
//위의 코드는 컴파일 불가, 가능하게하려면
static void mergeAll(List<String> one, List<String, two){
List<String>[] stringLists = {one, two};
}
List[] test = {List.of(1), List.of(2)}; // True
List<Integer>[] test2 = {List.of(1), List.of(2)}; // Error
안전하기 위해선 제네릭 배열에 아무것도 저장하거나 덮어쓰지 말고, 배열의 참조를 밖으로 노출시키지 말아야 한다.
제네릭 배열에 아무것도 저장하거나 덮어쓰지말고, 배열의 참조를 밖으로 노출시키지 말아야 한다.
제네릭과 가변인수를 함께 사용할 때에는 궁합이 잘 맞지 않으니 조심하자
//Key 가 wildcard Type
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));
}
}
//Get할 때 요청받은 타입의 value를 찾아 cast 하여 response함
public <T> void putFavorite(Class <T> type, T instance){
favorites.put(Objects.requireNonNull(type), type.cast(instance));
}
Favorites favorites = new Favorites();
Game game = favorites.putFavorite(Game.class, new Game());
//HashSet<Integer>에 string을 넣는 것 같은 문제를 막을 수 있다.
//TypeReference, ParameterizedTypeRefernece 등이 있다.
RestTemplate re = enw RestTemplate();
List<String> rest = re.exchange("http://localhost:8080", HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>()
{}).getBodt();