IT_Programming/Java

[펌] Generics 튜토리얼

JJun ™ 2009. 3. 24. 02:36

[ 출처: http://effective.springnote.com/pages/1616988 ] 

Generics 파라메터 타입

<T> : 자료형(Type) 으로 쓰일때 ...

<E> : 객체 내에서 하나의 요소(Element)로 사용될때

<K> : 전달 되는 객체가 키(Key) 값으로 사용될때

<V> : 전달 되는 객체가 값(Value) 으로 사용될때

 

<?> : 와일드카드 (unknown)

<? super 객체>    : 제한된 와일드카드 (해당 객체 또는 상위 객체)

<? extends 객체> : 제한된 와일드카드 (해당 객체 또는 하위 객체)

 

 

sun 튜토리얼   http://java.sun.com/docs/books/tutorial/extra/generics/index.html 

 

  1. 기존 방식
  2. List myIntList = new LinkedList();
  3. myIntList.add(new Integer(0));
  4. Integer x = (Integer) myIntList.iterator().next(); // 성가신 캐스팅 

  5. generics
  6. List<Integer> myIntList = new LinkedList<Integer>();
  7. myIntList.add(new Integer(0));
  8. Integer x = myIntList.iterator().next();
  9.  

 

  1.  java.util 패키지에 있는 List 와 Iterator 의 선언부
  2. public interface List<E>{
  3.     void add(E x);
  4.     Iterator<E> iterator();
  5. }
  6. public interface Iterator<E>{
  7.    E next();
  8.    boolean hasNext();
  9. }

gerneric 방식으로 타입인자를 선언한 것으로 List<Integer>는 Integer 대신 String을 사용할 수 없지만

이경우 에는 한번만 컴파일 되면 어떤 Element 라도 사용할수 있다.

 

  1. Generics 과 하위 타입
  2. List<String> ls = new ArrayList<String>(); // ArrayList 는 List의 하위 타입
    List<Object> lo = ls; // List<String>은 List<Object>의 하위타입이 아니다.
  3. lo.add(new Object());
    String s = ls.get(0); // error

 

  1. Wildcards
  2. // 기존 방식
  3.  void printCollection(Collection c) {
  4.      Iterator i = c.iterator();
  5.      for (k = 0; k < c.size(); k++) {
  6.           System.out.println(i.next());
  7.      }
  8. }
  9.  
  10. // 새로운 방식 -  Collection<Obect> 만 처리 가능
  11.  void printCollection(Collection<Object> c) {
  12.     for (Object e : c) {
  13.          System.out.println(e);
  14.     }
  15.  }
  16.  
  17.  // wildcards 사용 ( collection of unknown )
  18.  void printCollection(Collection<?> c) {
  19.       for (Object e : c) {
  20.              System.out.println(e);
  21.       }
  22. }

  23. // 임의의 Object를 add 하는 것은 안전하지 않다.
  24. Collection<?> c = new ArrayList<String>();
  25. c.add(new Object()); // Compile time error

 

  1.  Bounded Wildcards
  2. // any kind of shape
  3.  public void drawAll(List<? extends Shape> shapes) {
  4.         ...
  5. }

 

  1. Generic Methods
  2. // biginner's mistake
  3. static void fromArrayToCollection(Object[] a, Collection<?> c) {
  4.     for (Object o : a) {
  5.          c.add(o); // Compile time error
  6.     }
  7. }
  8. // generic method type declaration
  9. static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
  10.       for (T o : a) {
  11.             c.add(o); // Correct
  12.       }
  13. }
  14.  
  15. Object[] oa = new Object[100];
  16. Collection<Object> co = new ArrayList<Object>();
  17. fromArrayToCollection(oa, co); // T inferred to be Object
  18.  
  19. String[] sa = new String[100];
  20. Collection<String> cs = new ArrayList<String>();
  21. fromArrayToCollection(sa, cs); // T inferred to be String
  22. fromArrayToCollection(sa, co); // T inferred to be Object
  23.  
  24. Integer[] ia = new Integer[100];
  25. Float[] fa = new Float[100];
  26. Number[] na = new Number[100];
  27. Collection<Number> cn = new ArrayList<Number>();
  28. fromArrayToCollection(ia, cn); // T inferred to be Number
  29. fromArrayToCollection(fa, cn); // T inferred to be Number
  30. fromArrayToCollection(na, cn); // T inferred to be Number
  31. fromArrayToCollection(na, co); // T inferred to be Object
  32. fromArrayToCollection(na, cs); // compile-time error
  33.  

  34. // 언제 generic 메쏘드를 사용하고 어떤때 wildcards 타입을 사용할 것인가?
  35.           interface Collection<E> {
                  public boolean containsAll(Collection<?> c);
                  public boolean addAll(Collection<? extends E> c);
              }
              
  36. // generic 메쏘드를 사용하면 다음과 같다

    interface Collection<E> {

    public <T> boolean containsAll(Collection<T> c);

    public <T extends E> boolean addAll(Collection<T> c);

    }

  37. // generic 메쏘드는 두개 이상의 인자 사이의 타입 연관성을 위해 정의 된것이다. 또, wildcard는 인자의 하위 유연성을 위해 만들어졌다.
  38. // 다음과 같이 혼용해서 사용하는 경우도 있다.
    class Collections {
  39.       public static <T> void copy(List<T> dest, List<? extends T> src) { ...}
  40. }
  41. // wildcard 를 사용하지 않고 정의 하는 방법도 있다.
    class Collections {
  42.      public static <T, S extends T> void copy(List<T> dest, List<S> src) { ...}
  43. }
  44.  
  45. // 첫번짹 타입인자 T는 첫 번째 메쏘드 인자의 선언부와 두번째 타입인자 S를
  46. // 정의하기 위한 부분에 쓰였다.
  47. // S는 src의 타입을 정의 하기 위해 한번만 쓰였다.
  48. // 즉 S는 두번째 타입인자를 정의 하기 위한 곳 외에는 쓰이지 않았다.
  49. // 다른 곳에서 쓰이지 않았기 때문에 S는 wildcard로 변환 될수 있다.
  50. // 이런 경우 wildcard를 쓰는 것이 훨씬 명확하다.

 

 

  1. true or false ?
  2. List <String> l1 = new ArrayList<String>();
    List<Integer> l2 = new ArrayList<Integer>();
    System.out.println(l1.getClass() == l2.getClass());
  3. // erasure 에 의해 모든 타입 인자가 제거되므로 의미 없는 비교이다.

     

  4. // generics 클래스 인스턴스 인지 체크 하는 것은 불가 하다.
  5. Collection cs = new ArrayList<String>();
  6. if (cs instanceof Collection<String>) { ...}

--------------------------------------------------------------------------------------------------