제네릭스(Generics)와 와일드 카드

컴퓨터/Java 2012. 11. 8. 05:02

제네릭스(Generics)와 와일드 카드 


자바 jdk 1.5에서 가장 큰 변화 중의 하나를 꼽자면 역시 제네릭스다 제네릭스는 다양한 타입의 객체를 다루는 메서드나 프레임워크들을 사용할때 컴파일 시 타입체크를 해주는 기능으로 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄인다.

예를 들어보자

List list = new ArrayList(); 라는 선언을 하였다면 list에는 String형이든 Integer형이든 사용자가 만든 객체 클래스이든 뭐든간에 저장이 가능하였다. 그래서 꺼내쓸때에 형변환을 해서 일일히 체크해 줘야 했고 예외처리되는 경우도 허다했다. 그러나 제네릭스의 등장으로 이러한 불편함이 사라졌다.

List<String> list = new ArrayList<String>();

위와 같은 선언은 list에 String형만 받아들인다는 뜻이다. 그렇다면 상속관계에 대해서는 어떻게 처리될까?

class Product {};

class TV extends Product{}; 라는 클래스가 있다고 가정하자 그리고 Product가 들어가는 ArrayList를 매개변수로 받는 메서드를 정의한다.

public static void printAll(ArrayList<Product> list){};

그렇다면 printAll(new ArrayList<Product>())는 당연히 들어갈 수 있을것이다. 그러나 Product를 상속받은 TV는 어떨까? printAll(new ArrayLIst<TV>())가 들어갈 수 있을까? 

답은 X 이다. 이클립스에서 컴파일 오류가 난다. 오류를 보면 printAll을 바꾸란다 그럼 어떻게 바꿔야 할까?? 답은 extends에 있다. 여기서 와일드 카드가 등장하고 와일드 카드를 통해 상속관계를 정의해 주면 된다.


받아오는 매개변수의 제네릭스 형을 ? extends Product라고 정의해주면 Product를 상속받은 모든 클래스를 사용할 수 있다. 그리고 extends와 반대로 ? super TV 라고 정의해 주면 TV의 조상 타입들을 받아 올 수있다. 나는 오늘도 자바의 객체지향성의 놀란다....

보통 이렇게 사용하지 않고 public static <T extends Product> void printAll(ArrayList<T> list)라고 사용하여 코드의 간결성을 향상시킨다. 

* 인터페이스를 매개변수로 받는다고 해도 제네릭스에서는 implements 가 아닌 extends를 사용한다.


제네릭스의 장점

- 타입안정성을 제공한다.

- 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

설정

트랙백

댓글