본문 바로가기

Develop/JAVA

자바 제네릭에 대한 간단한 설명 (Generic, Generic Type Erasure)

제네릭이란?

제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다.

 

public class NoGenericArrayList {

  private int size;
  private Object[] elementData = new Object[5];

  public void add(Object value) {
  	elementData[size++] = value;
  }

  public Object get(int idx) {
  	return elementData[idx];
  }
}

 

위 코드는 제네릭을 사용하지 않고 구현한 ArrayList이다. 내부 데이터를 Object 타입으로 선언했기 때문에 데이터  타입에 관계 없이 5개 요소를 담을 수 있다. (자바의 모든 클래스는 Object 클래스를 상속받기 때문ㅇ)

 

public class NoGenericArrayListTest {

  public static void main(String[] args) {
    NoGenericArrayList list = new NoGenericArrayList();

    list.add(50);
    list.add(100);

    Integer value1 = (Integer) list.get(0); // 정상 실행!
    Integer value2 = (Integer) list.get(1); // 정상 실행!

    System.out.println(value1 + value2);
  }
}
public class NoGenericArrayListTest {

  public static void main(String[] args) {
    NoGenericArrayList list = new NoGenericArrayList();

    list.add("50");
    list.add("100");

    Integer value1 = (Integer) list.get(0); // 런타임 에러 발생
    Integer value2 = (Integer) list.get(1); // 런타임 에러 발생

    System.out.println(value1 + value2);
  }
}

다음 두 가지 경우의 차이는 잘못된 타입캐스팅 때문에 발생한다.

1번째 예제는 ArrayList 내부에 Integer 타입의 값을 넣은 뒤 다시 꺼내어 타입캐스팅하였다. (Object 타입으로 보관하기 때문)

 

하지만 2번째 예제에서는 String 타입으로 넣은 값을 꺼내어 Integer로 타입캐스팅하려고 시도했다.

물론 Object 타입으로 꺼냈기 때문에 컴파일 에러는 발생하지 않는다. 그러나 런타임 에러가 발생한다.

 

그렇다면 NoGenericArrayListForInteger, NoGenericArrayListForString 과 같이 데이터 타입에 따른 ArrayList를 별도로 구현할 수 있다. 하지만 코드의 중복이 발생하기 때문에 현명한 해결방법이라고 생각되지는 않는다.

제네릭 타입 소거 (Generic Type Erasure)