code

Reified Generic은 무엇입니까?

codestyles 2020. 11. 12. 08:15
반응형

Reified Generic은 무엇입니까? Type Erasure 문제를 어떻게 해결하며 큰 변경없이 추가 할 수없는 이유는 무엇입니까?


나는 주제에 대한 Neal Gafter의 블로그를 읽었 으며 여전히 많은 요점에 대해 명확하지 않습니다.

Java, JVM 및 기존 컬렉션 API의 현재 상태에서 유형 정보를 보존하는 컬렉션 API 구현을 만들 수없는 이유는 무엇입니까? 이전 버전과의 호환성이 유지되는 방식으로 향후 Java 버전의 기존 구현을 대체 할 수 없습니까?

예로서:

List<T> list = REIList<T>(T.Class);

REIList는 다음과 같습니다.

public REIList<T>() implements List {
  private Object o;
  private Class klass;

  public REIList(Object o) {
    this.o = o;
    klass = o.getClass();
  }
... the rest of the list implementation ...

그리고 메서드는 Object o와 Class klass를 사용하여 유형 정보를 얻습니다.

일반 클래스 정보를 보존하려면 JVM 구현 변경이 아닌 언어 변경이 필요한 이유는 무엇입니까?

내가 이해하지 못하는 것은 무엇입니까?


요점은 수정 된 제네릭은 유형 정보를 보존하기 위해 컴파일러에서 지원하는 반면 유형 삭제 된 제네릭은 지원하지 않는다는 것입니다. AFAIK, 처음에 타입 삭제의 요점은 이전 버전과의 호환성을 가능하게하는 것이 었습니다 (예 : 낮은 버전의 JVM은 여전히 ​​일반 클래스를 이해할 수 있음).

위와 같이 구현에 유형 정보를 명시 적으로 추가 할 수 있지만 목록을 사용할 때마다 추가 코드가 필요하며 제 생각에는 꽤 지저분합니다. 또한이 경우 직접 검사를 추가하지 않는 한 모든 목록 메서드에 대한 런타임 유형 검사가 없지만 수정 된 제네릭은 런타임 유형을 보장합니다.


대부분의 Java 개발자의 믿음과는 달리 컴파일 타임 유형 정보를 유지하고 매우 제한된 방식에도 불구하고 런타임에이 정보를 검색 할 수 있습니다. 즉, Java는 매우 제한된 방식으로 수정 된 제네릭을 제공합니다 .

유형 삭제에 대해

컴파일 타임에 컴파일러는 전체 유형 정보를 사용할 수 있지만이 정보는 일반적으로 이진 코드가 생성 될 때 유형 erasure 라는 프로세스에서 의도적 으로 삭제 됩니다. 이것은 호환성 문제로 인해 이러한 방식으로 수행됩니다. 언어 디자이너의 의도는 플랫폼 버전간에 완전한 소스 코드 호환성과 완전한 바이너리 코드 호환성을 제공하는 것이 었습니다. 다르게 구현 된 경우 최신 버전의 플랫폼으로 마이그레이션 할 때 레거시 애플리케이션을 다시 컴파일해야합니다. 수행 된 방식으로 모든 메서드 서명이 보존되고 (소스 코드 호환성) 아무것도 다시 컴파일 할 필요가 없습니다 (바이너리 호환성).

자바의 수정 된 제네릭 관련

컴파일 타임 유형 정보를 유지해야하는 경우 익명 클래스를 사용해야합니다. 요점은 익명 클래스의 매우 특별한 경우 런타임에 전체 컴파일 타임 유형 정보를 검색 할 수 있다는 것입니다. 즉, 수정 된 제네릭을 의미합니다.

이 주제에 대한 기사를 작성했습니다.

http://rgomes-info.blogspot.co.uk/2013/12/using-typetokens-to-retrieve-generic.html

이 기사에서는 사용자가 기술에 어떻게 반응했는지 설명합니다. 요컨대, 이것은 모호한 주제이며 기술 (또는 원하는 경우 패턴)은 대다수의 Java 개발자와 관련이 없습니다.

샘플 코드

위에서 언급 한 기사에는 아이디어를 실행하는 소스 코드에 대한 링크가 있습니다.


IIRC (및 링크 기반), Java 제네릭은 Object 컬렉션을 사용하고 앞뒤로 캐스팅하는 기존 기술에 대한 구문 설탕 일뿐입니다. 컴파일러가 컴파일시 유형 안전성 을 유지하는지 확인하기 위해 검사를 수행 할 수 있으므로 Java 제네릭을 사용하는 것이 더 안전하고 간단합니다 . 그러나 런타임은 완전히 다른 문제입니다.

반면 .NET 제네릭은 실제로 새로운 유형을 만듭니다 List<String>. C #의 a는 List<Int>. Java에서는 내부적으로 똑같은 것 List<Object>입니다. 즉, 각각 하나가 있으면 런타임에 볼 수없고 선언 된 내용을 볼 수 없으며 현재 상태 만 볼 수 있습니다.

수정 된 제네릭은이를 변경하여 Java 개발자에게 현재 .NET에 존재하는 것과 동일한 기능을 제공합니다.


나는 주제에 대한 전문가는 아니지만 내가 이해하기 때문에 컴파일 타임에 유형 정보가 손실됩니다. C ++에서와 달리 Java는 템플릿 시스템을 사용하지 않으며 유형 안전성은 전적으로 컴파일러를 통해 달성됩니다. 런타임에 List는 실제로 항상 List입니다.

그래서 필자는 유형 정보가 JVM이 없기 때문에 사용할 수 없다는 사실 때문에 언어 사양의 변경이 필요하다는 입니다.

참고 URL : https://stackoverflow.com/questions/879855/what-are-reified-generics-how-do-they-solve-type-erasure-problems-and-why-cant

반응형