Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics: Get name of instance

I have a method which returns a List<Property<?>>.

Property is a type having one generic parameter:

public class Property<T extends Comparable<T>> { ... }

Having a list of mixed-typed properties, I cannot know what type parameter a specific element has.

I would like to do something like that:

List<Property<?>> list = getList();
for(Property<?> crt : list)
{
    PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());
    //                        I know this doesn't exist ----^
}

In one sentence: I need the PropertyWrapper to have the same generic template argument as the current Property does. Is there any way to do this?

I could apply a suggestion as stated in https://stackoverflow.com/a/3437930/146003 but even if I do this, how to instanciate the appropriate PropertyWrapper<XXX> then, only having an instance of Class<T>?

I can modify Property<?> if required. I also don't mind if reflection needs to be used (I assume it needs to be)


EDIT: I forgot something. In fact I cannot instanciate the wrapper by the line

PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());

because I have specialized subclasses (PropertyWrapper_String).

Now I see two possibilities:

1: Instanciate the class by string:

String strGenericType = "";
Class<?> wrapperClass = Class.forName("PropertyWrapper_" + strGenericType);

2: Is there any way to specialize a generic class without creating a subclass?


Many thanks in advance for your tips

like image 791
Atmocreations Avatar asked Feb 06 '12 13:02

Atmocreations


People also ask

How do I get the classname from generic type?

You can see that in the main method, or in any instance method, I am capable to get the name of the generics type, in this case the main will print: java. lang. Integer. ...and you get the name of the subclass (if any).

How do I get a class instance of generic type T?

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. A solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

What is ParameterizedType in Java?

A parameterized type is an instantiation of a generic type with actual type arguments. A generic type is a reference type that has one or more type parameters. These type parameters are later replaced by type arguments when the generic type is instantiated (or declared ).

What is the name of the T in Java?

< T > is a conventional letter that stands for "Type", and it refers to the concept of Generics in Java.


1 Answers

Try creating the following method:

<T> PropertyWrapper<T> createWrapper(Property<T> property){
      return new PropertyWrapper<T>(property);
}

Then call it as such.

List<Property<?>> list = getList();
for(Property<?> crt : list)
{
    PropertyWrapper<?> crtWrapper = createWrapper(crt);
}

The reason the above works is that the generic type T is inferred from the argument and is locked down for the entire method. Unlike using <?> in the loop where each instance of <?> is inferred to be a different type.

Edit:

To deal with the issue of having a different class type depending on the class in the wrapper, consider a Map where the key is the class being wrapped and the value is the wrapper.

Map<Class<?>, Class<?>> myMap;

Then you could so something like this:

Class<?> wrappedType = property.getGenericType();
Class<?> wrapperClass = myMap.get(wrappedType);
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) wrapperClass.newInstance();

Although you might need to do something like this if you need to pass an argument.

Constructor<?> constructor = wrapperClass.getDeclaredConstructor(property.getClass());
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) constructor.newInstance(property);
like image 199
John B Avatar answered Sep 24 '22 16:09

John B