Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Advanced generic type reflection library with support for working with AnnotatedTypes (for Java 8+)

License

NotificationsYou must be signed in to change notification settings

leangen/geantyref

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Maven CentralJavadocBuild StatusLicense

A fork of the excellentGenTyRef library, adding support for working withAnnotatedTypes introduced in Java 8 plus many nifty features.

Table of Contents

Goal

This library aims to provide a simple way to analyse generic type information and dynamically create(Annotated)Type instances, all at runtime.

Overview

All functionality of the library is exposed via a handful of classes:

  • GenericTypeReflector : contains static methods used for generic type analysis
  • TypeFactory : contains static methods used forType/AnnotatedType instance creation
  • TypeToken : Used to createType/AnnotatedType literals (usingTHC pattern)

Usage

Maven:

<dependency>    <groupId>io.leangen.geantyref</groupId>    <artifactId>geantyref</artifactId>    <version>2.0.0</version></dependency>

Other build tools:

You can find instructions atmaven.org

Examples

Getting the exact return type of a method

The simplest example would be having a class similar to this:

classStringListextendsArrayList<String> {    ...}

Getting the exact return type ofStringList'sget method is rather difficult:

Methodget =StringList.class.getMethod("get",int.class);get.getGenericReturnType()//yields T, which is not very useful information

On the other hand, runningGenericTypeReflector.getExactReturnType(get, StringClass.class)would yieldString which is what we were looking for.

Getting the exact type of a field

Presume we have two simple classes:

classContainer<T> {publicTitem;}classNumberContainerextendsContainer<Number> {}

We again face issues when trying to discover the exact type of theitem field:

Fielditem =NumberContainer.class.getField("item");item.getGenericType();//yields T again

Instead,GenericTypeReflector.getExactFieldType(item, NumberContainer.class) returnsNumber as desired.

Getting the exact types of method parameters

GenericTypeReflector.getExactParameterTypes(methodOrConstructor, aType)

Getting the exact super type

If we had the classes defined as follows:

classContainer<T> {publicTitem;}classNumberContainer<TextendsNumber>extendsContainer<T> {}classLongContainerextendsNumberContainer<Long> {}

If we'd callLongContainer.class.getGenericSuperclass() it would correctly returnNumberContainer<Long>but getting from there toContainer<Long> is much more difficult, as there's no direct way.

GeantyRef allows us to simply callGenericTypeReflector.getExactSuperType(LongContainer.class, Container.class) to getContainer<Long>

Getting the exact sub type

Even more interestingly, it is sometimes possible to get the exact sub type of a type.For example, if we hadList<String> and we wantedArrayList<String> if would be possible,as theArrayList's sole type parameter is coming fromList, i.e.ArrayList does not defineany type parameters itself,List<String> already contains all the needed information.This is rather difficult to calculate using standard reflection, but if we already had a reference toList<String> calledlistOfString, it is enough to call:

GenericTypeReflector.getExactSubType(listOfString, ArrayList.class) to getArrayList<String>

Still, how to get tolistOfString? Probably by calling one of the methods described above.But, it's also possible to create a type literal directly viaTypeToken, or construct the desiredType (List<String>) dynamically usingTypeFactory.

Getting annotated return/parameter/field/sub/super types

It is worth noting that all the basic methods on theGenericTypeReflector listed above haveoverloads that work withAnnotatedTypes.

classPerson {publicList<@NonNullString>nicknames;}AnnotatedTypelistOfNonNullStrings =Person.class.getField("nicknames").getAnnotatedType();Methodget =List.class.getMethod("get",int.class);//returns an AnnotatedType representing: @NonNull StringAnnotatedTypenonNullString =GenericTypeReflector.getExactReturnType(get,listOfNonNullStrings);

Similarly,getExactFieldType,getExactParameterTypes,getExactSuperType,getExactSubTypework withAnnotatedTypes.

Creating type literals usingTypeToken

This approach, known asTypesafe Heterogenous Container (THC) ortype token, is widely usedin libraries like Jackson or Gson that need to work with generic types. There are various sourcesdescribing the intricacies of this approach,Neal Gafter's blog being a classic one.

To obtain aType instance representing a know generic type, such asList<String> it is enough todo the following:

Type listOfString = new TypeToken<List<String>>(){}.getType();

What we're doing here is creating an anonymous subclass of a parameterized type (TypeToken) andgetting it's generic super class viagetGenericSuperclass.

Creating annotated type literals usingTypeToken

If instead we wanted an instance of an annotated type, such asList<@NonNull String>, the sameprinciple would apply:

AnnotatedType listOfNonNullString = new TypeToken<List<@NonNull String>>(){}.getAnnotatedType();

Creating types dynamically usingTypeFactory

TypeToken is only useful if all the generic type information is known ahead of time. It will notallow us to create aType orAnnotatedType dynamically. For such a task,TypeFactory providesadequate methods.

Class<List>listType =List.class;Class<String>typeParameter =String.class;//returns a Type representing List<String>TypelistOfStrings =TypeFactory.parameterizedClass(listType,typeParameter);Class<Map>mapType =Map.class;Class<String>keyTypeParameter =String.class;Class<Number>valueTypeParameter =Number.class;//returns a Type representing Map<String, Number>TypemapOfStringNumber =TypeFactory.parameterizedClass(mapType,keyTypeParameter,valueTypeParameter);

Creating annotated types dynamically usingTypeFactory

TypeFactory can also produceAnnotatedType instances, but this means we need to somehow obtaininstances of the annotations themselves (instances ofAnnotation).An obvious way of getting them would be from an existingAnnotatedElement (annotatedElement.getAnnotations()).Class,Parameter,Method,Constructor,Field all implementAnnotatedElement.

But,TypeFactory also allows you to instantiate anAnnotation dynamically:

Map<String,Object>annotationParameters =newHashMap<>();annotationParameters.put("name","someName");MyAnnotationmyAnnotation =TypeFactory.annotation(MyAnnotation.class,annotationParameters);

This produces anAnnotation instance as if@MyAnnotation(name = "someName") was found in the sources.

Armed with this knowledge, it's easy to produce anAnnotatedType:

Class<List>listType =List.class;Class<String>typeParameter =String.class;Annotation[]annotations = {myAnnotation };//returns an AnnotatedType representing: @MyAnnotation(name = "someName") List<String>AnnotatedTypeannotatedListOfString =TypeFactory.parameterizedClass(listType,annotations,typeParameter);

Turning anyType into anAnnotatedType

GenericTypeReflector also allows you to wrap anyType into anAnnotatedType by collecting itsdirect annotations. For example:

@SuppressWarnings("unchecked")classSomething {}//returns an AnnotatedType representing: @SuppressWarnings("unchecked") SomethingAnnotatedTypesomething =GenericTypeReflector.annotate(Something.class);

This method will correctly turn aParameterizedType into anAnnotatedParameterizedType,WildcardType into anAnnotatedWildcardType etc.

To turn aParameterizedType into anAnnotatedParameterizedType with customized annotations:

TypelistOfStrings =TypeFactory.parameterizedClass(List.class,String.class);Annotation[]typeAnnotations = {myAnnotation };Annotation[]argumentAnnotations = {anotherAnnotation };//Get an AnnotatedParameterizedType representing: @MyAnnotation List<@AnotherAnnotation String>AnnotatedParameterizedTypeannotatedListOfAnnotatedStrings =parameterizedAnnotatedType(listOfStrings,typeAnnotations,argumentAnnotations);

More

There are more features provided byGenericTypeReflector that were not described in depth here,like the possibility to replace annotations on anAnnotatedType viareplaceAnnotations,or update them viaupdateAnnotations, calculate hash codes and check equality ofAnnoatedTypes(asequals andhasCode are not overridden in Java'sAnnotatedType implementations) etc, sofeel free to explore a bit on your own.

Wiki

More info can be found at the projectWiki.

License

Apache 2.0

About

Advanced generic type reflection library with support for working with AnnotatedTypes (for Java 8+)

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java100.0%

[8]ページ先頭

©2009-2025 Movatter.jp