Search code examples
javagenericstype-erasure

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


Solution

  • Okay I'm going to answer myself.

    I'm now passing an instance of Class<?> to the Property-class.

    Then I extract the basic name of the property and simply cut away "java.lang." which is possibly as in most cases, I'm doing this to primitive data types - resp. their autoboxing classes.

    Further, I just instanciate a new instance of the wrapper by name and pass the to be wrapped property as a parameter to the constructor which applys for that.

    Here some code for the interested ones among you:

    String template = "..."; // some package definition
    for (Property<?> crt : bag)
    {
        String className = template + crt.getClassName();
        Class<? extends PropertyWrapper<?>> wrapperClass = null;
        wrapperClass = (Class<? extends PropertyWrapper<?>>) Class.forName(className);
        Constructor<? extends PropertyWrapper<?>> constructor = wrapperClass.getConstructor(new Class<?>[] {Property.class});
        PropertyWrapper<?> wrapper = constructor.newInstance(crt);
        // Further operations using the wrapper
    }
    

    for simplicity, I left out the error handling part.