자바에서 제네릭 배열을 어떻게 생성하나요?


자바 제네릭 구현 때문에, 아래와 같이 구현할 수가 없습니다:

public class GenSet<E> {
    private E a[];

    public GenSet() {
        a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
    }
}

타입의 안전성을 유지하면서 어떻게 구현할 수 있을까요?

이전에 자바 포럼에서 다음과 같은 해결책을 찾아보았습니다.

import java.lang.reflect.Array;

class Stack<T> {
    public Stack(Class<T> clazz, int capacity) {
        array = (T[])Array.newInstance(clazz, capacity);
    }

    private final T[] array;
}

그런데 위의 소스코드가 어떻게 동작하는지 잘 이해가 되지 않습니다. 도와주세요.

  • 2016년 05월 20일에 작성됨

조회수 361


1 답변


좋아요
0
싫어요
채택취소하기

질문에 대한 답을 차례로 설명하겠습니다.

클래스 GenSet은 "checked"인가요? "unchecked"인가요? 그것의 의미를 아시나요?

  • Checked: strong typing을 의미합니다. strong typing이란 서로 다른 데이터 유형의 객체 간의 상호 작용을 제한하는 것이지요. 한마디로 강력하게 타입 체크를 한다고 이해하셔도 되겠지요. GenSet을 checked로 정의하면, GenSetClass<E>를 입력으로 받는 생성자를 정의하여 객체들의 타입이 무엇인지를 명확히 알 수 있어서 만약 타입이 E가 아닌 객체가 메소드의 입력으로 전달되면 메소드들은 익셉션을 발생하게 됩니다. Collections.checkedCollection을 참고하세요.

이와 같은 경우로 정의하면, 다음과 같은 코드로 구현할 수 있겠지요:

public class GenSet<E> {

    private E[] a;

    public GenSet(Class<E> c, int s) {
        // Use Array native method to create array
        // of a type only known at run time
        @SuppressWarnings("unchecked")
        final E[] a = (E[]) Array.newInstance(c, s);
        this.a = a;
    }

    E get(int i) {
        return a[i];
    }
}
  • Unchecked: weak typing을 의미합니다. 즉, 타입 체크가 약하다는 것이겠지요. 그래서 메소드의 입력으로 객체를 전달할 때 그 객체의 타입을 체크하지 않습니다.

이와 같은 경우로 정의하면, 다음과 같은 코드로 구현할 수 있습니다.

public class GenSet<E> {

    private Object[] a;

    public GenSet(int s) {
        a = new Object[s];
    }

    E get(int i) {
        @SuppressWarnings("unchecked")
        final E e = (E) a[i];
        return e;
    }
}

배열의 변수타입은 타입 파라미터에 대하여 타입 소거 (type erasure)되어야 한다는 점을 주의해야 합니다. 타입 소거는 소스코드에 있는 타입 정보는 런타임시에는 불필요하기 때문에 컴파일시 제거된다는 것입니다.

public class GenSet<E extends Foo> { // E has an upper bound of Foo

    private Foo[] a; // E erases to Foo, so use Foo[]

    public GenSet(int s) {
        a = new Foo[s];
    }

    ...
}

이것이 자바 제네릭의 약점입니다. "제네릭" 클래스는 실행시 정해지는 구체화된 타입이 무엇인지 알지 못하기 때문에, 타입 소거로 구현하여야 합니다. 그러므로 타입 체크와 같은 몇몇 명확한 메커니즘이 구현되지 않으면 타입의 안전성을 보장할 수가 없겠지요.

  • 2016년 05월 21일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close