Generic
목차
  - 제네릭이란?
 
  - 제네릭 타입
 
  - 제네릭 메서드
 
  - 와일드카드
 
  - 제네릭 타입 소거
 
1. 제네릭 이란?
  - 컴파일 타임에 타입을 체크함으로써 코드의 안정성을 높여주는 기능
 
  List<T>   // 타입 매개 변수
  List<String>  stirngList = new ArrayList<String>();
      // 매개변수화된 타입
 
1) 컴파일 타임에 강력한 타입 검사
  List stringList = new ArrayList<>();
  stringList.add("BoB");
  stringList.add(1);
  String result = (String) stringList.get(0) + (String) stringList.get(1);    // Runtime Error !
 
  List<String> stringList = new ArrayList<>();
  stringList.add("BoB");
  stringList.add(1);    // Compile Error !
 
2) 캐스팅(타입 변환) 제거
  List stringList = new ArrayList<>();
  stringList.add("BoB");
  String result = (String) stringList.get(0);
 
  List<String> stringList = new ArrayList<>();
  stringList.add("BoB");
  String result = stringList.get(0);
 
3) 변성
1) 배열 vs 제네릭 타입
  Object[] objectArray = new Integer[1];
 
  List<Object> objectList = new ArrayList<Integer>(); // Compile Error !
 
2) 무공변(Invariance) - <T>
  - 타입 B가 타입 A의 하위 타입일때, Category
<B>가 Category<A>의 하위 타입이 아닌 경우. 
  - 즉 아무런 관계가 없다.
 
3) 공변(Convariance) - <? extends T>
  - 타입 B가 타입 A의 하위 타입일 때
 
  - Category
<B>가 Category<A>의 하위 타입인 경우. 
4) 반공변(Contravariance) - <? super T>
  - 타입 B가 타입 A의 하위 타입일 때
 
  - Category
<B>가 Category<A>의 상위 타입인 경우. 
2. 제네릭 타입 (Generic Types)
1) Class<T> interface<T>
  class Category {
      private Object object;
      public void set(Object object){
        this.object = object;
      }
      public Object get(){
        return object;
      }
  }
 
  class Category<T>{
    private T t;
    public void set(T t){
      this.t = t;
    }
    public T get(){
      return t;
    }
  }
 
3. 제네릭 메서드 (Generic Methods)
  class NoodleCategory<T>{
    private T t;
    public void set(T t){
      this.t = t;
    }
    public T get(){
      return t;
    }
    public <T> void printClassName(T t){
        System.out.println("클래스 필드에 정의된 타입 = " + this.t.getClass().getName());
        System.out.println("제네릭 메서드에 정의된 타입 = " + t.getClass().getName());
    }
  }
  NoodleCategory<Noodle> noodleCategory = new NoodleCategory<>();
  noodleCategory.set(new Noodle());
  noodleCategory.printClassName(new Pasta());
 
1) 제네릭 타입 제한의 필요성
  class NoodleCategory<T>{
    private T t;
    public void set(T t){
      this.t = t;
    }
    public T get(){
      return t;
    }
  }
  NoodleCategory<Noodle> noodleCategory = new NoodleCategory<>();   // OK
  NoodleCategory<Coke> cokeNoodleCategory = new NoodleCategory<>(); // ????
 
2) 제한된 제네릭 타입
class NoodleCategory<T extends Noodle>{
    private T t;
    public void set(T t){
      this.t = t;
    }
    public T get(){
      return t;
    }
  }
  NoodleCategory<Noodle> noodleCategory = new NoodleCategory<>();
  NoodleCategory<Ramen> ramenNoodleCategory = new NoodleCategory<>(); // OK
  NoodleCategory<Coke> cokeNoodleCategory = new NoodleCategory<>(); // Compile Error !
 

4. 와일드 카드
1) <?> Unbounded Wildcards

2) <? extends Noodle> Upper Bounded Wildcards

3) <? super Noodle> Lower Bounded Wildcards

4) 제한
class NoodleCategory<T>{
    private T t;
    public void set(T t){
      this.t = t;
    }
    public T get(){
      return t;
    }
  }
class CategoryHelper {
  public void popNoodle(Category<? extends Noodle> category){
    Noodle noodle = category().get();   // 꺼내는 건 OK
    category.set(new Noodle());         // 저장은 NO
  }
  public void pushNoodle(Category<? super Noodle> category){
    category.set(new Noodle());       // 저장은 OK
    Noodle noodle = category.get();   // 꺼내는건 NO
  }
}
 
4-1) 언제 무엇을 써야할까?
  - PECS
 
  - producer - extends, consumer - super
 
5) 와일드 카드 producer - extends
  class NoodleCategory<E>{
    private List<E> list = new ArrayList<>();
    public void pushAll(Collection<? extends E> box){
      for(E e : box){
        list.add(e);
      }
    }
  }
 
6) 와일드 카드 consumer - super
  class NoodleCategory<E>{
    private List<E> list = new ArrayList<>();
    public void popAll(Collection<? super E> box){
      box.addAll(list);
      list.clear();
    }
  }
 
5. 제네릭 타입 소거
  - 타입 매개변수의 경계가 없는 경우에는 Object
 
  - 경계가 있는 경우에는 경계 타입으로 타입 파라미터를 변경
 
  - 타입 안전성을 유지하기 위해 필요한 경우 타입 변환 추가
 
  - 제네릭 타입을 상속 받은 클래스의 다형성을 유지하기 위해 Bridge method 생성
 
출처
그린론의 제네릭
        
      
      
      
      
  
     
    
      
    
  
댓글남기기