Java Generics의 수퍼 유형 토큰

1. 개요

이 튜토리얼에서는 수퍼 유형 토큰에 익숙해지고 런타임시 일반 유형 정보를 보존하는 데 어떻게 도움이되는지 살펴볼 것입니다.

2. 삭제

때로는 특정 유형 정보를 메소드에 전달해야합니다 . 예를 들어, 여기에서는 Jackson이 JSON 바이트 배열을 문자열 로 변환 할 것으로 예상합니다 .

byte[] data = // fetch json from somewhere String json = objectMapper.readValue(data, String.class);

이 기대치를 리터럴 클래스 토큰 (이 경우 String.class )을 통해 전달 합니다.

그러나 제네릭 유형에 대해 동일한 기대치를 쉽게 설정할 수는 없습니다.

Map json = objectMapper.readValue(data, Map.class); // won't compile

Java는 컴파일 중에 일반 유형 정보를 지 웁니다. 따라서 제네릭 형식 매개 변수는 소스 코드의 아티팩트 일 뿐이며 런타임에는 사라집니다.

2.1. 수정

기술적으로 말해서 일반 유형은 Java로 수정되지 않습니다. 프로그래밍 언어의 용어에서 유형이 런타임에 존재하면 유형이 수정되었다고 말합니다.

Java에서 수정 된 유형은 다음과 같습니다.

  • long 과 같은 단순 기본 유형
  • String 또는 Runnable 과 같은 비 일반적인 추상화
  • List 또는 HashMap 과 같은 원시 유형
  • 모든 유형이 List 또는 HashMap 과 같은 제한되지 않은 와일드 카드 인 일반 유형
  • String [], int [], List [] 또는 Map [] 과 같은 다른 수정 된 유형의 배열

결과적으로 Map 이 수정 된 유형이 아니기 때문에 Map.class 와 같은 것을 사용할 수 없습니다 .

3. 슈퍼 타입 토큰

결과적으로, 컴파일 시간 동안 유형 정보를 보존하기 위해 Java의 익명 내부 클래스의 힘을 활용할 수 있습니다.

public abstract class TypeReference { private final Type type; public TypeReference() { Type superclass = getClass().getGenericSuperclass(); type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; } public Type getType() { return type; } }

이 클래스는 추상이므로 여기에서 하위 클래스 만 파생 할 수 있습니다.

예를 들어 익명의 내부를 만들 수 있습니다.

TypeReference token = new TypeReference() {};

생성자는 형식 정보를 유지하기 위해 다음 단계를 수행합니다.

  • 먼저이 특정 인스턴스에 대한 일반 슈퍼 클래스 메타 데이터를 가져옵니다.이 경우 일반 슈퍼 클래스는 TypeReference입니다.
  • 그런 다음 일반 수퍼 클래스에 대한 실제 유형 매개 변수를 가져와 저장합니다.이 경우에는 Map이됩니다.

제네릭 유형 정보를 보존하기위한이 접근 방식을 일반적으로 수퍼 유형 토큰이라고합니다 .

TypeReference token = new TypeReference() {}; Type type = token.getType(); assertEquals("java.util.Map", type.getTypeName()); Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments(); assertEquals("java.lang.String", typeArguments[0].getTypeName()); assertEquals("java.lang.Integer", typeArguments[1].getTypeName());

수퍼 유형 토큰을 사용하여 컨테이너 유형이 Map이고 유형 매개 변수가 StringInteger 임을 알 수 있습니다.

이 패턴은 너무 유명해서 Jackson과 같은 라이브러리와 Spring과 같은 프레임 워크에는 자체 구현이 있습니다. JSON 객체를 Map 으로 구문 분석하는 것은 수퍼 유형 토큰으로 해당 유형을 정의하여 수행 할 수 있습니다.

TypeReference token = new TypeReference() {}; Map json = objectMapper.readValue(data, token);

4. 결론

이 튜토리얼에서 우리는 런타임에 일반 유형 정보를 보존하기 위해 수퍼 유형 토큰을 사용하는 방법을 배웠습니다.

평소처럼 모든 예제는 GitHub에서 사용할 수 있습니다.