I am trying to reason about generics at runtime. There are several great libraries to do this (e.g., gentyref, ClassMate and Guava). However, their usage is a little over my head.
Specifically, I want to extract an expression which matches a particular field in the context of a subclass.
Here is an example using gentyref:
import com.googlecode.gentyref.GenericTypeReflector;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
public class ExtractArguments {
public static class Thing<T> {
public T thing;
}
public static class NumberThing<N extends Number> extends Thing<N> { }
public static class IntegerThing extends NumberThing<Integer> { }
public static void main(final String... args) throws Exception {
final Field thing = Thing.class.getField("thing");
// naive type without context
Class<?> thingClass = thing.getType(); // Object
System.out.println("thing class = " + thingClass);
Type thingType = thing.getGenericType(); // T
System.out.println("thing type = " + thingType);
System.out.println();
// exact types without adding wildcard
Type exactThingType = GenericTypeReflector.getExactFieldType(thing, Thing.class);
System.out.println("exact thing type = " + exactThingType);
Type exactNumberType = GenericTypeReflector.getExactFieldType(thing, NumberThing.class);
System.out.println("exact number type = " + exactNumberType);
Type exactIntegerType = GenericTypeReflector.getExactFieldType(thing, IntegerThing.class);
System.out.println("exact integer type = " + exactIntegerType);
System.out.println();
// exact type with wildcard
final Type wildThingType = GenericTypeReflector.addWildcardParameters(Thing.class);
final Type betterThingType = GenericTypeReflector.getExactFieldType(thing, wildThingType);
System.out.println("better thing type = " + betterThingType);
final Type wildNumberType = GenericTypeReflector.addWildcardParameters(NumberThing.class);
final Type betterNumberType = GenericTypeReflector.getExactFieldType(thing, wildNumberType);
System.out.println("better number type = " + betterNumberType);
final Type wildIntegerType = GenericTypeReflector.addWildcardParameters(IntegerThing.class);
final Type betterIntegerType = GenericTypeReflector.getExactFieldType(thing, wildIntegerType);
System.out.println("better integer type = " + betterIntegerType);
System.out.println();
System.out.println("desired thing type = T");
System.out.println("desired number thing type = N extends Number");
System.out.println("desired integer thing type = Integer");
}
}
And here is the output:
thing class = class java.lang.Object
thing type = T
exact thing type = class java.lang.Object
exact number type = class java.lang.Object
exact integer type = class java.lang.Integer
better thing type = capture of ?
better number type = capture of ?
better integer type = class java.lang.Integer
desired thing type = T
desired number thing type = N extends Number
desired integer thing type = Integer
I know the betterThingType
Type
object (a gentyref-specific implementation) is more sophisticated than what is shown by toString()
here. But I am guessing I need to invoke getExactFieldType
again with a non-wildcard Type
to get what I'm looking for.
My main requirement is that I need an expression which could become part of a code-generated source file that could be successfully compiled—or at least compiled with minimal modification. I am open to using whatever library is best for the job.
Aucun commentaire:
Enregistrer un commentaire