지네릭스
지네릭란 ?
Generic이라는 단어가 주는 의미처럼 다양한 타입에 적용할 수 있도록 지원하는것, 타입(클래스, 인터페이스)에 정의 가능하며 메소드 정
의 또한 가능
class Box<T> {
T item;
public Box(T string) {
this.item = string
}
public T getItem() {
return this.item;
}
}
위와 같이 지네릭 클래스를 선언할수 있다. 그 후 참조변수와 생성자에 타입 T대신 사용될 실제 타입을 지정해야 한다. 아래코드를 보면
객체를 선언한 타입과 대입할 데이터 타입은 일치해야한다는 것을 알 수 있다.
Box<Strirng> b = new Box<String>();
b.setItem(new Object()); //에러 String 외 다른타입은 지정불가
b.setIem("ABC"); //Ok
지네릭의 특징
- 런타임에 발생하는 오류처리에서 발생하는 손실 비용을 최소화 할수 있따
- Generic을 적용할 경우 별도의 변환 과정을 필요로 하지 않음
- 다양한 타입의 객체들을 다루는 메소드나 컬렉션 클래스에 컴파일 시 타입 체크를 가능하도록함
위에 적은 세번째 특징을 알기 쉽게 아래 코드를 보면서 알아보자
public static <T extends Comparable<T>> void bubbleSort(T[] items) {
for(int i = items.legnth - 1; i > 0 ; i--) {
for(int j = 0; j < 1 ; j++) {
if(items[j].compareTo(item[j+1]) > 0) {
T item = items[j];
items[j] = items[j+1];
items[j+1] = item;
}
}
}
}
버블 정렬은 각 항목의 비교를 통해 항목의 순서를 정렬하는 잘 알려진 알고리즘이다. 일반적인 버블 정렬 알고리즘은 하나의 타입에 대한
정렬을 수행하지만 지네릭스는 항목간 비교가 가능한 Comparable 항목이라면 정렬 가능한 일반적인 알고리즘 작성을 가능하게 한다.
즉 버블소트가 Integer 타입과 String 타입에도 정렬을 가능하게 함으로써 메소드하나로 다양한 타입의 정렬을 할수 있게 한다.
지네릭 타입의 선언
지네릭 타입의 선언은 일반 타입 선언에 타입 파라미터 < > 를 추가한 형태로 사용한다
또한 하나 이상의 타입 파라미터를 사용할 수 있다.
class Pair<K, V> {
private K key;
private V value;
public K getKey() {
return this.key;
}
public V getValue() {
return this.value;ㅈ
}
}
주의 사항
- 지네릭 타입 생성장에서는 타입 파라미터를 사용하지 않는다.
- 참조 변수와 생성자에 주어지는 타입 파라미터는 동일해야 함.
- 타입 파라미터의 상속 관계는 지네릭 타입 생성시 영향을 주지 않음
- 타입 파라미터가 명확한 경우, 생성자 호출시 전달되어야 하는 타입 변수는 생략 가능
지네릭 메소드
메소드의 변수가 타입변수가 선언된 것. **클래스의 타입 매개변수
메소드를 시그너처의 타입 파라미터는 호출시 생략이 가능하다.
지네릭 메소드 선언
<Access Modifier> <Type Parameter List> <Return Type> Method name(Parameter list)
지네릭 메소드의 선언은 일반 메소드 선언과 동일하며, 일반화할 타입을 타입 파라미터로 선언한다. 메소드는 타입 파라미터의 목록을 가
져야 하며, 메소드 선언에 타입 파라미터 목록을 선언 해야한다.
public class GenericMethod {
public <T> List<T> arrayToList(T[] array) {
List<T> list = new LinkedList<T>();
for(T t : array) {
list.add(t);
}
return list;
}
public static void main(String [] args) {
Integer[] array = {1,2,3};
GenericMethod me = new ();
List<Integer> List = me.<Integer>arrayToList(array);
}
}
타입 파라미터
지네릭스 타입은 타입 파라미터가 필요하며,타입 파라미터에는 기존 데이터 타입을 제외한 모든 타입을 사용 할 수 있으며, 정의되는 타입
내에서는 변수 선언의 타입으로 사용된다.
타입 파라미터 명명규칙
- E : 요소 (Element)
- K : 키 (Key)
- N: 숫자 (Number)
- T: 타입 (Type)
- V: 값 (Value)
- S,U,V 등 - 2번째, 3번째, 4번째 등
E(element)는 그 의미로 요소라고 해석할 수 있다.
예를 들어 ArrayList는 요소들(오브젝트)를 배열처럼 저장 하기 때문에 E로 선언되어야 한다.
즉, List에서는 E(Element) 가 어울린다.
결론은 컬렉션 클래스와 같이 배열 기반으로 되어 있는 구조에는 E가 어울리고, 그 외에는 T 가 어울린다.
와일드 카드
와일드 카드는 지네릭을 정의할 때 return 값에 대한 특정한 타입 파라미터를 정의하지 않고 임의의 타입이 올 수 있는 기능을 제공한다.
지네릭 파라미터의 와일드 카드는 <?> 형식으로 정의되며, 인자로 받을 수 있는 타입의 제한이 가능하다
<? extends T> : 상한 경계 : T 클래스를 상속하는 자식클래스들만 올 수 있다.
<? super T> : 하한 경계 : T 클래스의 부모 클래스만 올 수 있다. (더 제한적임)
<?> = <? extends Object> : 기존 경계 : 오브젝트 타입을 상속하는 모든 타입이 들어올 수 있다.
타입 파라미터 제약
-
타입 파라미터 인자로 기본 데이터 타입을 사용할 수 없음
-
타입 파라미터 변수의 객체를 생성할 수 없음
-
static 필드로 선언할 수 없음
-
지네릭 타입은 타입변환 될 수 없으며 instance of 연산자를 사용 할 수없음
-
지네릭 타입의 배열은 생성할 수 없음
-
Exception 타입의 서브 타입이 될 수 없음