목차
- 제네릭이란?
- 제네릭 클래스
- 제네릭 메서드
1. 제네릭이란?
다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시 타입 체크를 해주는 기능
객체의 타입을 컴파일시 체크하기 때문에 객체 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.
제네릭의 특징
타입 안정성
타입체크/형변환 생략으로 코드 간결성
2. 제네릭 클래스
2.1 제네릭 제한 사항
- 타입 변수는 인스턴스 변수로 간주, static 멤버가 될 수 없음
class Box<T> {
static T item; //에러
static int compare(T t1, T t2) { //에러
}
왜냐하면 제네릭은 인스턴스 별로 다르게 동작하려고 만든 기능이기 때문이다.
- 배열 생성 X, 선언만 가능
- 타입 변수는 상속 관계에 있더라도 에러
Box<Fruit> appleBox = new Box<Apple>(); // 에러 (apple의 Fruit의 자손)
2.2 제한된 제네릭 클래스
제네릭은 클래스, 메소드의 타입을 제한한다. 하지만 들어갈 수 있는 타입을 제한하진 못한다. 이를 보완하기 위해 상속을 사용한다.
제네릭은 클래스, 메소드의 타입을 제한한다.
FruitBox<Apple> appleBox = new FruitBox<>(); // only Apple
FruitBox<Orang> orangeBox = new FruitBox<>(); // only Orange
그러나 들어갈 수 있는 타입을 제한하진 못한다.
FruitBox<NoteBook> appleBox = new FruitBox<>(); // NoteBook 은 넣기 싫은데... 제한하질 못함
그래서 상속을 쓴다.
class FruitBox<T extends Fruit>
2.3 와일드 카드, ?
- 생성과 선언에서 타입 변수가 다르다면(상송 관계더라도) 오류
- 타입 변수는 컴파일 단계에서 사라진다. 그래서 오버로딩 되지 않음
그런데 제네릭 클래스를 매개변수로 받는 메서드를 사용하고 싶다. 그래서 고안된 것이 와일드 카드
class Juicer {
static Juice makeJuice(FruitBox<Fruit> box) { //Fruit 은 타입 변수지만 이미 결정됐기 때문에
String tmp = ""; //static과 함께 사용 가능
for (Fruit fruit : box.getFruits()) {
tmp += fruit + " ";
}
return new Juice(tmp);
}
하지만 문제는 static 메서드이다. 누구를 넣든 동일하게 동작해야 되기 때문에 자손을 넣을 수 없다.
(static 메서드가 아니더라도 타입 변수의 특성상 오류 발생한다.)
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
System.out.println(juicer.makeJuice(fruitBox)); // OK
System.out.println(juicer.makeJuice(appleBox)); //에러
해결책으로 오버로딩. 하지만 제네릭 타입이 다른 것만으로는 오버로딩이 성립하지 않는다.
제네릭 타입은 컴파일러가 컴파일할 때만 사용하고 제거해버린다.
그래서 두 메서드는 오버로딩이 아니라 메서드 중복 정의
그래서 고안된 것이 와일드 카드(?)
static Juice makeJuice(FruitBox<? extends Fruit> box) {
String tmp = "";
for (Fruit fruit : box.getFruits()) {
tmp += fruit + " ";
}
return new Juice(tmp);
}
Fruit을 상속하는 모든 것을 받을 수 있다는 뜻
3. 제네릭 메서드
메서드 선언부에 제네릭 타입이 선언된 메서드를 제네릭 메서드라 한다.
제네릭 타입 선언 위치 - 반환 타입 바로 앞
static <T> void sort(List<T> list, Comparator<? super T> c)
제네릭 메서드 해석
제네릭 메서드를 실제로 만들어 쓰는 것 보단 자바 API를 쓸 때, 제네릭 메서드를 잘 알고 있으면 도움이 될 것 같음
public static <T extentds Comparable<? super T>> void sort(List<T> list)
sort 매서드 매개변수 List 는 Comparable 인터페이스를 구현한 것이어야 한다. 그리고 T의 부모는 모두 사용 가능하다.
'Java' 카테고리의 다른 글
Java - 애너테이션 (0) | 2023.03.21 |
---|---|
자바 - 람다식 (0) | 2022.11.26 |
애노테이션이란? (0) | 2022.07.17 |
기본형과 참조형 그리고 래퍼클래스 (0) | 2022.07.17 |
this는 왜 사용할까? (0) | 2022.07.15 |