给出像
这样的通用界面interface DomainObjectDAO<T>
{
T newInstance();
add(T t);
remove(T t);
T findById(int id);
// etc...
}
我想创建一个指定类型参数的子接口:
interface CustomerDAO extends DomainObjectDAO<Customer>
{
// customer-specific queries - incidental.
}
实现需要知道实际的模板参数类型,但当然类型擦除手段在运行时不可用。我可以包含一些注释来声明接口类型吗?像
这样的东西 @GenericParameter(Customer.class)
interface CustomerDAO extends DomainObjectDAO<Customer>
{
}
然后,实现可以从接口获取此批注,并将其用作运行时泛型类型访问的替代。
一些背景知识:
此接口使用JDK动态代理实现,如here所述。这个接口的非泛型版本运行良好,但使用泛型更好,而不必在子接口中创建方法只是为了指定域对象类型。泛型和代理处理大多数事情,但在运行时需要实际类型来实现newInstance
方法等。
答案 0 :(得分:7)
通过调用以下方法,可以找到Dao子接口(CustomerDAO)的实际类型参数:
import java.lang.reflect.ParameterizedType;
public static Class<?> getDomainClass(final Class<?> daoInterface) {
ParameterizedType type = (ParameterizedType) daoInterface.getGenericInterfaces()[0];
return (Class<?>) type.getActualTypeArguments()[0];
}
当您将其称为
时Class<?> domainClass = getDomainClass(daoInterface);
使用daoInterface == CustomerDAO.class
,您将获得domainClass == Customer.class
。
在我的实现中,DaoFactory
执行此调用并使用domainClass
作为DaoInvocationHandler
的构造函数参数。
答案 1 :(得分:1)
实现需要知道实际的模板参数类型。
当然,CustomerDao
隐式的任何实现都知道类型参数是Customer
。它正在实施DomainObjectDAO<Customer>
而不是DomainObjectDAO<T>
。
如果CustomerDao
类扩展了泛型抽象类,并且该泛型抽象类需要知道T
的实际类型,那么问题才会出现。但是你可以通过将T
的Class对象(在本例中为Customer.class
)作为构造函数参数传递给超类来处理它。