자바의 정석 chapter 12

inho ha·2022년 3월 10일
0

자바의 정석

목록 보기
13/18

지네릭스(Generics)

다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능

장점
1. 타입 안정성을 제공
2. 타입체크와 형변환을 생략할 수 있어 코드가 간결해짐

지네릭 클래스

class Box {
	Object item;
    
    void setItem(Object item) { this.item = item; }
    Object getItem() { return item; }
}

클래스 옆에 < T> 를 붙이고 Object를 T로 바꾸면 지네릭 클래스가 된다

class Box<T> {
	T item;
    
    void setItem(T item) { this.item = item; }
    T getItem() { return item; }
}

T : 타입 변수, T가 아닌 다른 문자 사용 가능
타입 변수가 여러개인 경우 <K, V> 이렇게 콤마로 나열하면 된다.

이후 지네릭 클래스 객체를 생성할 때 T 대신 사용할 타입을 지정해줘야함

Box<String> b = new Box<String>();
b.setItem(new Object()); // String 타입이 아니므로 에러
b.setItem("ABC");
String item = b.getItem(); // 형변환이 필요없음

클래스에 String 만 가능하도록 하려면 클래스 정의에서 T 대신에 String 을 넣어주면 된다.

지네릭 타입

지네릭 타입은 컴파일할 때 검사이후 제거된다.

static멤버는 타입 변수를 사용할 수 없다.

지네릭 타입의 배열은 선언하는 것은 가능하지만 생성하는 것은 안된다.
new 연산자는 컴파일 시점에서 T가 어떤 타입인지 정확하게 알아야 하는데 불가능하기 때문
지네릭 배열을 꼭 생성해야 할 경우 newInstance() 와 같이 동적으로 객체를 생성하는 메서드로 배열을 생성하거나, Object 배열을 생성해서 복사한다음 T[]로 형변환 하는 방법등을 사용한다.

제한된 지네릭 타입

class FruitBox<T extends Fruit> {
}

지네릭 타입에 extends를 사용하면 특정 타입의 자손들만 대입할 수 있도록 제한할 수 있다.

class FruitBox<T extends Fruit & Eatable> {
}

인터페이스를 구현해야하는 경우도 extends를 쓰고
위와 같이 사용하면 Fruit의 자손이면서 Eatable을 구현한 클래스만 사용가능하도록 제한할 수 있다.

와일드 카드

< ? extends T> : T와 그 자손들만 가능
< ? super T> : T와 그 조상들만 가능
< ?> : 모든 타입이 가능

매개변수로 지네릭 클래스를 받는 경우 지네릭 타입을 다양하게 받기 위해서 오버로딩을 하게되면 메서드 중복 정의 에러가 된다.
지네틱 타입은 컴파일 이후 사라지기 때문에 지네릭 타입이 다른 것 만으로는 오버로딩이 성립되지 않는다.
이때 와일드 카드를 사용해주면 된다.

지네릭 메서드

메서드의 반환 타입 바로 앞에 < T>를 붙여 주어 지네릭 메서드를 만들수 있다.

static <T> void sort(List<T> list, Comparator<? super T> c)

지네릭 클래스 내부에서 지네릭 메서드가 선언된 경우 같은 T를 사용해도 지네릭 메서드의 T와는 별개다

<Fruit>sort(list, c);

지네릭 메서드를 호출할 때는 앞에 타입을 명시해줘야한다.
그러나 대부분 컴파일러가 타입을 추정할 수 있기 때문에 생략해도 된다.
지네릭 메서드를 호출할 때는 this. 이나 클래스명. 은 생략 불가

지네릭 타입의 형변환

지네릭 타입과 원시타입간의 형변환 가능

대입된 타입이 다른 지네릭 타입 간에 형변환 불가
와일드 카드가 포함된 지네릭 타입으로 형변환은 가능

profile
iha / ian / inho ha

0개의 댓글