Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Tags
more
Archives
Today
Total
관리 메뉴

forDevLife

[자바의정석] Chap 12. 지네릭스 본문

Java

[자바의정석] Chap 12. 지네릭스

JH_Lucid 2021. 2. 26. 12:33

1.1 ~ 1.5) 지네릭스 주요 정리

- 반드시 타입을 지정하여 지네릭스 경고가 나오지 않도록 하자.(호환성을 유지하기 위해 지네릭스 사용안한 코드를 허용하는 것일 뿐)

- static 멤버에는 타입변수 사용 불가하다. 모든 객체에 동일하게 동작해야 하므로

- 지네릭 타입의 배열 생성 허용하지 않는다.(참조변수 선언은 가능)

    -. T[] itemArr; // ok, T타입의 배열을 위한 참조변수

    -. T[] tmpArr = new T[itemArr.length]; // error, 지네릭 배열 생성 불가 - 컴파일 시점에 T가 뭔지 모르므로 에러 발생

    -. 같은 이유로, instanceof 연산자 / new 연산자에서도 사용 불가

    -. 꼭 사용해야 하는 경우, 'Reflection API'의 newInstnace()와 같이 동적으로 객체를 생성, 또는 Object 배열에서 복사 후 T[]로 형 변환

- <? extends T> : 와일드 카드의 상한 제한, T와 그 자손들만 사용 가능

- <? super T>    : 와일드 카드의 하한 제한, T와 그 조상들만 가능

-  <?>                : 제한 없음, 모든 타입이 가능. <? extends Object>와 동일 기능

 

- static <T> void sort(List<T> list, Comparator<? super T> c) 와 같이 Collections.sort()가 정의되어있다.

여기에서 정렬하고자 하는 List를 입력하면, 예를 들어 fruit를 상속받는 apple을 타입 변수로 지정한다고 가정하자.

List<apple> list, Comparator<? super apple> c 와 같이 정리가 되는데, 이때 Comparator로 올 수 있는 항목은 다음과 같다.

1. Comparator<apple>

2. Comparator<fruit>

3. Comparator<Object>

 

따라서, 2번 이상의 Comparator를, fruit를 상속받는 class들 끼리 공용으로 사용 가능하다.

 

1.6) 지네릭 메서드

 

- 메서드 선언부에 지네릭 타입이 선언된 메서드. 선언 위치는 반환 타입 바로 앞이다.

   ex) static <T> void sort(~)

- 지네릭 메서드는 일반 클래스에서도 정의될 수 있다.

- 지네릭 클래스 내에 지네릭 메서드가 정의되었을 때, 여기서 정의된 두 타입변수는 전혀 별개의 것이다. 즉 지네릭 메서드에 정의된 타입변수는 그 안에서마 사용되는 지역 변수라고 생각하면 된다.

- 매개변수의 타입이 복잡할 때, 유용하게 사용된다.

 

1.7) 지네릭 타입의 형변환

 

- 지네릭 & non-지네릭간의 형변환은 항상 가능(경고는 발생)

- 대입된 타입이 다른 지네릭 타입일 경우에는 형변환 불가.

   -. Box<Object> objBox = new Box<String>(); // 타입이 달라 형변환 불가

   -. Box<? extends Object> objBox = new Box<String>(); // 이 경우에는 형변환 가능해진다. 

   -. 위의 항을 좌 우 변경해도 가능하지만, 경고는 발생한다. 즉,

      Box<? extends Object> objBox = null;

      Box<String> stringBox = (Box<String>)objBox; // 가능하지만 경고 발생.

 

- 정리하자면, 1) 와일드카드가 포함된 지네릭 타입으로도 형변환 가능, 2) 그 반대(but warning)로도 형변환이 가능하다.

 

    Optional<? extends Object> wopt = new Optional<Object>();  -> 1) 와일드카드가 포함된 지네릭 타입으로 변경 가능

    Optional<Object>                  oopt = new Optional<Object>();

    Optional<String>                   sopt = (Optional<String>)wopt;   -> 2) 그 반대, 즉 와일드카드가 포함된 걸 다른 타입으로 변경 가능

    Optional<String>                   sopt = (Optional<String>)oopt;    // 이건 에러. oopt가 와일드카드가 포함된 지네릭이 아니므로.

 

- 마지막으로, 와일드카드가 사용된 지네릭 타입끼리도 형변환이 가능(마찬가지로 경고)

 

1.8) 지네릭 타입의 제거

- 컴파일러는 지네릭 타입 이용하여 소스파일 체크하고, 필요한 곳에 형변환을 넣어준다.

- 그 다음 지네릭을 제거한다. 즉 컴파일된 파일(*.class)에는 지네릭 타입에 대한 정보가 없다. 하위 호환성을 위해.

 

 

Comments