지네릭스 (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의 경우 수정이 가능하다.