How to get a class instance of generics type T

2018-12-31 02:49发布

I have a generics class, Foo<T>. In a method of Foo, I want to get the class instance of type T, but I just can't call T.class.

What is the preferred way to get around it using T.class?

标签: java generics
17条回答
初与友歌
2楼-- · 2018-12-31 03:05

Actually, I suppose you have a field in your class of type T. If there's no field of type T, what's the point of having a generic Type? So, you can simply do an instanceof on that field.

In my case, I have a

List<T> items;
in my class, and I check if the class type is "Locality" by

if (items.get(0) instanceof Locality) ...

Of course, this only works if the total number of possible classes is limited.

查看更多
十年一品温如言
3楼-- · 2018-12-31 03:05

I'm using workaround for this:

class MyClass extends Foo<T> {
....
}

MyClass myClassInstance = MyClass.class.newInstance();
查看更多
萌妹纸的霸气范
4楼-- · 2018-12-31 03:09

I was looking for a way to do this myself without adding an extra dependency to the classpath. After some investigation I found that it is possible as long as you have a generic supertype. This was OK for me as I was working with a DAO layer with a generic layer supertype. If this fits your scenario then it's the neatest approach IMHO.

Most generics use cases I've come across have some kind of generic supertype e.g. List<T> for ArrayList<T> or GenericDAO<T> for DAO<T>, etc.

Pure Java solution

The article Accessing generic types at runtime in Java explains how you can do it using pure Java.

Spring solution

My project was using Spring which is even better as Spring has a handy utility method for finding the type. This is the best approach for me as it looks neatest. I guess if you weren't using Spring you could write your own utility method.

import org.springframework.core.GenericTypeResolver;

public abstract class AbstractHibernateDao<T extends DomainObject> implements DataAccessObject<T>
{

    @Autowired
    private SessionFactory sessionFactory;

    private final Class<T> genericType;

    private final String RECORD_COUNT_HQL;
    private final String FIND_ALL_HQL;

    @SuppressWarnings("unchecked")
    public AbstractHibernateDao()
    {
        this.genericType = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractHibernateDao.class);
        this.RECORD_COUNT_HQL = "select count(*) from " + this.genericType.getName();
        this.FIND_ALL_HQL = "from " + this.genericType.getName() + " t ";
    }
查看更多
不再属于我。
5楼-- · 2018-12-31 03:10

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.

A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}
查看更多
旧人旧事旧时光
6楼-- · 2018-12-31 03:11

I had this problem in an abstract generic class. In this particular case, the solution is simpler:

abstract class Foo<T> {
    abstract Class<T> getTClass();
    //...
}

and later on the derived class:

class Bar extends Foo<Whatever> {
    @Override
    Class<T> getTClass() {
        return Whatever.class;
    }
}
查看更多
临风纵饮
7楼-- · 2018-12-31 03:11

It's possible:

class Foo<T> {
  Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}

You need two functions from svn/trunk/dao/src/main/java/com/googlecode/genericdao/dao/ DAOUtil.java.

For more explanations, see Reflecting generics.

查看更多
登录 后发表回答