제네릭.

제네릭의 이점을 최대한 살리고 단점을 최소화하는 방법을 이야기함

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

private final Collection stamps = ...;
stamps.add(new Coin(...));

for (Iterator i = stamps.iterator(); i.hasNext(); ) {
  Stamp stamp = (Stamp) i.next(); // ClassCastException을 던짐
}
private final Collection<Stamp> stamps = ...;
static int numElementsInCommon(Set s1, Set s2) {
  int result = 0;
  for (Object o1: s1)
    if (s2.contains(o1))
      result++;
  return result;
}
static int numElementsInCommon(Set s1, Set s2)
if (o instanceof Set) {
  Set<?> s = (Set<?>)o;
}

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

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

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

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

public static Set union(Set s1, Set s2) {
  Set result = new HashSet(s1);
  result.addAll(s2);
  return result;
}

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
  Set<E> result = new HashSet<>(s1);
  result.addAll(s2);
  return result;
}

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

public void pushAll(Iterable<E> src) {
  for(E e: src) {
    push(e);
  }
}
public void pushAll(Iterable<? extends E> src) {
  for (E e: src) {
    push(e);
  }
}
public void popAll(Collection<E> dst) {
  while(!isEmpty()) {
    dst.add(pop());
  }
}

Stack<Number> numberStack = new Stack<>();
Collection<Object> objects = ...;
numberStack.popAll(objects);
public void popAll(Collection<? super E> dst) {
  while(!isEmpty()) {
    dst.add(pop());
  }
}

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

static void dangerous(List<String>... stringLists) {
  List<Integer> intList = List.of(42);
  Object[] objects = stringLists;
  objects[0] = intList; // 힙오염
  String s = stringLists[0].get(0); //ClassCastException을
}

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

public class Favorites {
  private Map<Class<T>, Obejct> favorites = new HashMap<>();

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

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


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 favoritesString = 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());
}