Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I build a Java type object at runtime from a generic type definition and runtime type parameters?

Assuming a generic type declaration (Java)

class Foo<T> {
    public T bar;
}

how can I, at runtime, instantiate a Type object that represents Foo parameterized over a specific type T (also known only at runtime)?

like image 672
SoftMemes Avatar asked Feb 02 '12 11:02

SoftMemes


People also ask

How do you make an Object of a generic class?

Like C++, we use <> to specify parameter types in generic class creation. To create objects of a generic class, we use the following syntax. Note: In Parameter type we can not use primitives like 'int','char' or 'double'.

How does Java determine objects at Runtime?

Object. getClass() method is used to determine the type of object at run time. Return Type: Returns the Class objects that represent the runtime class of this object.

Is Object created at Runtime in Java?

Objects in Java are only created at Runtime. Objects are created runtime by Java Virtual Machine based on classes that you create as a programmer.

Can you create instances of generic type parameters?

A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the MakeGenericType method.


2 Answers

I think I understand your question. You want to serialize a Foo<T>, and you have the class object of T at runtime (but it's not fixed at compile time). Therefore, the suggested solution in Gson of creating an anonymous subclass of TypeToken does not work because that requires that the parameterized type (e.g. Foo<String>) be hard-coded at compile time, and it does not work if you use something like Foo<T>.

However, let's look at what the TypeToken method on the Gson site actually accomplishes. You create an object of an anonymous subclass of TypeToken, and then ask for its type parameter using its getType() method. A class's superclass is part of its metadata, and includes the generic parameters of its superclass. So at runtime, it can look at its own inheritance hierarchy, and figure out what type parameter you used for TypeToken, and then returns a java.lang.reflect.Type instance for that type (which, if it is parameterized, will be a ParameterizedType instance). Once you get this Type instance, you are supposed to pass it as the second argument of the toGson().

All we need to do is find another way to create this instance of ParameterizedType. ParameterizedType is an interface, but unfortunately the public Java API does not provide any concrete implementations or any way to create a ParameterizedType dynamically. There appears to be a class called ParameterizedTypeImpl, in the private Sun APIs and in the Gson code that you can use (e.g. here). You can simply copy the code and rename it into your own class. Then, to create a Type object representing Foo<String> at runtime, you can just do something like new ParameterizedTypeImpl(Foo.class, new Type[]{String.class}, null) (untested)

like image 190
newacct Avatar answered Sep 28 '22 06:09

newacct


Let's say we're talking about List<String> for example.
You can construct something like this:

    Type type = new ParameterizedType() {
            public Type getRawType() {
                return List.class;
            }

            public Type getOwnerType() {
                return null;
            }

            public Type[] getActualTypeArguments() {
                return new Type[] { String.class};
            }
        };

If you need this for de-serializing from JSON, you can use this Type from calling gson.fromJson

like image 34
AlexV Avatar answered Sep 28 '22 06:09

AlexV