본문 바로가기

Knowledge Wiki/Java

JAVA 제네릭

1. 제네릭
    Runtime 에러를 컴파일 에러 수준에서 catch하려는 노력.
    제네릭을 쓰면 타입 체크가 강화됨
    객체의 타입 안정성을 높이고 형 변환의 번거로움을 줄여줌.
    형변환 잘못할 시 ClassCastException()이 발생하는 데 이 예외를 컴파일 단계에서 차단할 수 있음.

ArrayList list = new ArrayList(); // JDK 1.5 이전, 제네릭 도입 이전
ArrayList<Object> list = new ArrayList<Object>(); // JDK 1.5 이후

 

2. 제한된 제네릭 클래스
    extends 키워드로 대입할 수 있는 타입을 제한

class FruitBox<T extends fruit & Eatable>{
	ArrayList<T> list = new ArrayList<T>();
}

FruitBox<Apple> appleBox = new FruitBox<Apple>(); // OK
FruitBox<Toy> toyBox = new FruitBox<Toy>(); // Error. Toy는 Fruit의 자손이 아님

 

3. 타입 변수에 대입은 인스턴스 별로 다르게 가능하다.

Box<Apple> appleBox = new Box<Apple>();
Box<Grape> grapeBox = new Box<Grape>();


    그래서 static 멤버에 타입 변수 사용은 불가하다. (인스턴스마다 다를 수 있으니까)

class Box<T> {
	static T item; // Error
	static int compare(T t1, T t2) { ... } // Error
}


    배열 생성할 때 타입 변수 사용불가. 타입 변수로 배열 선언은 가능

class Box<T> {
	T[] itemArr;

	T[] toArray(){
		T[] tmpArr = new T[itemArr.length]; // Error
	}
}


4. 와일드 카드 <?>
    하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능

    <? extends T> 와일드 카드의 상한 제한. T와 그 자손들만 가능
    <? super T> 와일드 카드의 하한 제한. T와 그 조상들만 가능
    <?> 제한 없음. 모든 타입이 가능. <? extends Object>와 동일

    보통 <? extends T>를 많이 씀.

5. 클래스의 타입 매개변수<T>와 메서드의 타입 매개변수 <T>는 별개이다.
    범위에 따른 Instance Variable과 Local Variable의 차이와 유사

6. 제네릭 메서드는 호출할 때마다 타입을 대입해야하지만 대부분 생략 가능하다.

7. 제네릭 메서드와 와일드 카드는 비슷한 일을 하지만 다른 용도로 사용된다.
    제네릭 메서드: 메서드를 호출할 때마다 다른 제네릭 타입을 대입할 수 있게 한 것 
    와일드 카드: 하나의 참조 변수로 서로 다른 타입이 대입된 여러 제네릭 객체를 다루기 위한 것

8. 원시 타입과 제네릭 타입 간의 형변환은 바람직하지 않다.
    JDK 1.5 이후로는 원시 타입 자체보단 제네릭 타입으로 쓰는 게 애초에 좋음.

Box<Object> objBox = null;
Box box = (Box) objBox; // 경고
Box<Object> objBox = (Box)box ; // 경고

'Knowledge Wiki > Java' 카테고리의 다른 글

JAVA 쓰레드  (0) 2021.12.01
JAVA Runtime 에러를 줄이기 위한 노력  (0) 2021.12.01
JAVA 해싱(Hashing)  (0) 2021.12.01
JAVA Collections 패키지  (0) 2021.12.01
JAVA Comparable, Comparator  (0) 2021.12.01