Home NhnAcademy 선발교육과정 15일차 (지네릭스)
Post
Cancel

NhnAcademy 선발교육과정 15일차 (지네릭스)

지네릭스 (Generic) 란?

  • 사전적 의미
    • 일반적인
    • 총칭의
    • 포괄적인

강력한 타입 검사

  • 타입 안정성(Type safety)를 지원
    • 타입 파라미터를 통해 전달된 타입 정보를 이용하여 컴파일 타입에 검사
    • 지네릭스 타입이 명확히 명시됨으로 컴파일 타입에 오류를 검출할 수 있음
    • 지네릭이 적용되지 않는 코드에서 일반적인 데이터를 처리하기 위해서는 데이터 최상위 타입인 java.lang.Object로 처리함.

런타임 오류 방지

  • 지네릭스를 사용하지 않고 코드를 작성할 경우 컴파일 단계에서 알수가 없다. 그러므로 꼭 사용하자.

Checked Exception

  • RuntimeException을 상속하지 않는 Exception…
  • 반드시 예외처리를 해야되는 Exception..
    • FileNotFoundException
    • ClassNotFoundException

Unchecked Exception

  • RuntimeException 상속한 Exception
  • 예외처리를 강제화 하지 않는다.
    • ArrayIndexOutOfBoundsException
    • NullPointException

타입 파라미터 명명 규칙

  • E : 요소 (Element)
  • K : key
  • V : value
  • N : Number
  • T : Type
  • S , U , V : 2번째 , 3번째 , 4번쨰

타입 제한

  • 제네릭 파라미터로 지정된 인스턴스의 동작은 공변적
    1
    2
    3
    4
    5
    6
    7
    
    public class Test01 {
      public static void main(String[] args) {
          Box<Number> box = new Box<Number>();
          box.add(Integer.valueOf(10));
          box.add(Double.valueOf(10.1));
      }
    }
    

    이렇게 상위객체가 제네릭 파라미터로 지정되었을때 하위객체가 들어가는 것은 가능하다.

  • 타입 파리미터는 반공변적
    • 아래 예제는 컴파일 오류 ..즉 Number -> Number 형태로 타입 파라미터를 타입을 사용해야 합니다.

Box<Number> box1 = new Box<Integer>();

하지만 Box전체를 넘겨줄때는 컴파일 오류가 발생한다.

와일드 카드

  • 파라미터나 return 값에 대해 특정한 타입 파라미터를 정의하지 않고 의의의 타입을 지정할 수 있다.
  • extends : 특정 타입 또는 상속받은 타입으로 타입 인자를 제한

  • void genericMethod(List<? extends Number>){...}

Number 하위 클래스 타입만 가능하다.

  • 특정 타입 또는 상위 타입으로 타입 인자를 제한 ( 반공변성)
  • void genericMethod(List<? super Number>) { … }

  • 무제한 와일드 카드
    • 타입 인자에 제한을 두지 않음
  • void genericMethod(Collection collection) { … }

지네릭에서의 타입 삭제

  • 지네릭 타입 파라미터는 컴파일시 모두 삭제됨
  • 타입 파라미터가 제한되지 않는 경우, Object 타입으로 변환됨
  • 타입 제한이 있는 경우, 해당 타입으로 변경됨

  • 타입 파라미터를 가지는 클래스 Node는 타입 파라미터 제한이 없으므로 컴파일러는 Object로 대처 한다.

공변성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Example{

  public static void main(String[] args) {
    List<Long> longList = Arrays.asList(10l, 20l, 30l, 40l, 50l);
    List<Double> doubleList = Arrays.asList(10.1d,20.1d,30.1d,40.1d,50.1d);
    List<Integer> integerList = Arrays.asList(10,20,30,40,50);

    System.out.println(total(longList));
    System.out.println(total(doubleList));
    System.out.println(total(integerList));

    List<Object> target = new ArrayList<>();
    target.add(10);
    target.add(20);
    target.add(30);
    putItem(target,10);

    System.out.println(getItem(longList,0));
    System.out.println(getItem(doubleList,0));
    System.out.println(getItem(integerList,0));
  }
  public static double total(List<? extends Number>numberList){//(List<Number>numberList)
    double total= 0;

    for(int i=0; i<numberList.size(); i++) {
      total += numberList.get(i).doubleValue();
    }    return total;
  }
}

위와 같은 코드에 다향성에 대한 이점을 확용하지 못함으로 이런문제를 해결하기 위해서 공변성, 반공변성에 대해서 이해해야 합니다.

1
2
3
4
  public static void putItem(List<? super Number> dest , Number number){
    boolean add = dest.add((number));
    System.out.println(dest.add(number));
  }

super의 경우 수정이 가능하다.

This post is licensed under CC BY 4.0 by the author.