如何获得泛型类型T的类实例
我有一个泛型类Foo<T>
。 在Foo
一个方法中,我想获得类型T的类实例,但我不能调用T.class
。
什么是使用T.class
解决它的首选方法?
简单的答案是,没有办法找到Java中泛型类型参数的运行时类型。 我建议阅读Java教程中关于类型擦除的章节以获取更多细节。
一个流行的解决方案是将类型参数的Class
传递给泛型的构造函数,例如
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
}
}
我正在寻找一种方法来做到这一点,而无需增加对类路径的额外依赖。 经过一番调查,我发现,这是可能的,只要你有一个通用的超类型。 这对我来说是好的,因为我正在使用带有泛型层超类型的DAO层。 如果这符合你的方案,那么这是最新的方法恕我直言。
我遇到的大多数泛型用例都具有某种通用超类型,例如ArrayList<T>
List<T>
ArrayList<T>
或DAO<T>
GenericDAO<T>
等。
纯Java解决方案
在Java中运行时访问泛型类型的文章解释了如何使用纯Java来完成它。
Spring解决方案
我的项目使用的是Spring,因为Spring有一个方便的实用方法来查找类型。 这对我来说是最好的方法,因为它看起来很棒。 我猜如果你不使用Spring,你可以编写你自己的实用程序方法。
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 ";
}
然而,有一个小漏洞:如果你将你的Foo
类定义为抽象类。 这意味着你必须将你的类实例化为:
Foo<MyType> myFoo = new Foo<MyType>(){};
(注意最后的双括号。)
现在,您可以在运行时检索T
的类型:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
但是请注意, mySuperclass
必须是实际定义T
的最终类型的类定义的超类。
它也不是很优雅,但你必须决定你是否喜欢new Foo<MyType>(){}
或new Foo<MyType>(MyType.class);
在你的代码中。
例如:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
然后:
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'n", s );
}
}
链接地址: http://www.djcxy.com/p/49627.html