개발/Java

non-reifiable 타입이란

하프킴 2021. 5. 17. 13:00
728x90

비 구체화 타입(non-reifiable type) : 타입 소거자에 의해 컴파일 타임에 타입 정보가 사라지는 것(런타임에 구체화하지 않는 것)

구체화 타입(reifiable type) : 자신의 타입 정보를 런타임 시에 알고 지키게 하는 것 (런타임에 구체화하는 것). 런타임 시에 완전하게 오브젝트 정보를 표현할 수 있는 타입

 

제너릭 타입 소거 : 원소 타입을 컴파일 타임에만 검사하고 런타임에는 해당 타입 정보를 알 수 없는 것. 다른 말로는 컴파일 타임에만 제약 조건을 적용하고, 런타임에 타입에 대한 정보를 소거하는 프로세스.

  • Primitives, non-generic types, raw types 등이 있다.

 

non-reifiable 문제는 자바에서 제네릭을 사용하지 않는 버전과의 호환성을 위해서 제공했던 기능 때문에 발생.

 

하위호환성을 위해 객체의 타입 정보를 컴파일 시에 확인하여 동일한 동작을 보장하여 Runtime 전에 소거함.

 

아래는 컴파일 이전과 이후의 코드이다. List<String>는 ArrayList로 변경되면서 타입 정보가 사라진 것을 확인할 수 있다.

Object[] 배열은 Long[] 배열 형태의 실제 타입으로 변경된 것을 확인할 수 있다.

// before
public static void main(String... args) {
  List<String> list = new ArrayList<>();
  list.add("Hi");

  Object[] array = new Long[10];
  array[0] = 1L;
}

// after
public static void main(String... var0) {
  ArrayList var1 = new ArrayList();
  var1.add("Hi");
  Long[] var2 = new Long[10];
  var2[0] = Long.valueOf(1L);
}

 

 

 

예시: 

 

첫번째 매개변수에는 추가된느 데이터가 저장되는 Collection을 구현한 클래스의 객체

두번째 매개변수에는 추가되는 객체들이 나열되도록 되어 있음

 

public static <T> boolean addAll(Collection<? super T>c, T... elements )

 

public void addData() {
	ArrayList<ArrayList<String>> list = new ArrayList(); // ArrayList내에 ArrayList<String>이 저장되는 list라는 객체 추가
    ArrayList<String> newDataList<new ArrayLIst<>; // newDataListㅇ라는 객체를 생성하고, 값을 하나 추가
    newDataList.add("a"); // Collections의 addAll() 메소드를 사용하여 list에 newDataList라는 객체를 저장하도록 했음.
    
    

 

Java6에서 컴파일 하면 unchecked generic array creation of tpye ..  이라는 경고가 발생함.

 

가변 매개변수를 사용하면

public static <T> boolean addAll(Collection<? super T> c, T... elements)

 

 

가변매개변수를 사용할 경우에 실제로 내부적으로는 다음과 같은 Object의 배열로 처리됨.

public static boolean addAll(java.util.Collection c, java.lang.Object[] elements);

 

 

이렇게 배열로 처리되면, 잠재적으로 문제가 발생할 수 있다. 

이 경고를 없애려면 @SafeVarags라는 어노테이션을 메소드 선언부에 추가하면 된다.

 

https://medium.com/@joongwon/java-java%EC%9D%98-generics-604b562530b3