Home > other >  Pass class type as argument with subtype
Pass class type as argument with subtype

Time:07-10

How can i create an instance of the given generic type class with a subtype Class<Foo<Bar>> type = ??

Its easy for simple generic such as: Class<Foo> type = Foo.class; but how to do this here?

final Class<Foo<Bar>> type = null; // ???

We cannot do something like Foo<Bar>.class which is possible in c# as far as i know.

I want to use this type in a generic function which works for all simple generics but not if nested.

Foo<Bar> fooBar = getRecord(type, 1);

static T get(Class<T> type, int id)
{
    // load from database
    return session.get(type, id);
}

Complex example

The production example is more complex having a DAO class with many methods that rely on the generic type.

interface Entity {}
class Foo<T extends Entity> extends Entity {}
class Bar extends Entity {}

class EntityDAO<T extends Entity> 
{
    Class<T> type;
    Session session;

    public EntityDAO(Class<T> type)
    {
        this.type = type;
    }

    public T get(int id)
    {
        return session.get(type, id);
    }
}

public class TestSession
{
    public <T> T get(final Class<T> type, final int id)
    {
        Objects.requireNonNull(type);
        return null;
    }

}

void static main(String[] args)
{
    final Class<Foo<Bar>> type = null; 

    // how to set type here?
    EntityDAO<Foo<Bar>> fooBarDAO = new EntityDAO<>(type);

    Foo<Bar> entity = fooBarDAO.get(1);

}

Currently i am just using the main type Foo.class loosing the Bar.class information for the DAO.

CodePudding user response:

With any workaround using Class<Foo<Bar>> type; as a variable the <Bar> is lost at runtime but still we can achieve the EntityDAO class to be as generic to support Foo<Bar> for easier code allow type to extend T inside the constructor / method and cast like:

@SuppressWarnings("unchecked")
public <V extends T> TestDAO(final Class<V> type)
{
    this.type = (Class<T>) type;
}

Then use it:

void static main(String[] args)
{
    // <Bar> information lost at runtime but not important
    EntityDAO<Foo<Bar>> fooBarDAO = new EntityDAO<>(Foo.class);

    // dao perfectly generic for Foo<Bar>
    Foo<Bar> entity = fooBarDAO.get(1);
}

This way we can use it without a dummy instance as @Japhei stated in his comment (which works with the original code) but not always a dummy instance is easy to create or available.

CodePudding user response:

If you have an instance of this type you could cast it to the specific class:

Foo<Bar> foo = new Foo<>();
type = (Class<Foo<Bar>>) foo.getClass();
  • Related