我正在尝试为我的数据库创建自己的存储库,所以我尝试这样的事情:
@Override
public <T extends DatabaseObject> List<T> getList() {
Cursor cursor = getCursor(somehowGetClassOfT(), null, null); //how to do this?
//excess code removed, rest of function not relevant to question
return list;
}
protected <T extends DatabaseObject> Cursor getCursor(Class<T> clazz, String selection, String[] selectionArgs) {
DatabaseObject databaseObject = instantiateFromT(clazz); //how to do this?
String tableName = databaseObject.getTableName();
String[] projection = databaseObject.getProjection();
String sortOrder = databaseObject.getDefaultOrderColumn() + " " + DEFAULT_SORT_ORDER;
Cursor cursor = database.query(
tableName,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
return cursor;
}
换句话说,我有许多扩展DatabaseObject的类,我希望能够动态地为它们构造一个Cursor。
我已经在DatabaseObject中定义了基本方法,例如获取表名,列名的String数组等,但由于我不能通过接口覆盖静态方法(对于像表名这样的东西),我必须实例化一个空白对象所以我可以用getter获取表名。
但是,我不确定如何实施:
somehowGetClassOfT()
。无论T
是什么,我都希望将它传递给Cursor函数。
instantiateFromT(clazz)
。给定一些类,调用构造函数,以便我可以访问该对象的table / projection / sort字段。
或者通过使用我一直听到的“反射”来实现这一切吗?
答案 0 :(得分:4)
泛型在运行时不具体化。由于信息不存在,您有两种解决方案:
这是一个带有私有字段T和构造函数的示例,从代码开始:
public abstract class MyRepository<T extends DatabaseObject> {
private Class<T> type;
public MyRepository(Class<T> type) {
this.type = type;
}
public <T> List<T> getList() {
Cursor cursor = getCursor(null, null); // how to do this?
// excess code removed, rest of function not relevant to question
return null;
}
protected <T extends DatabaseObject> Cursor getCursor(String selection, String[] selectionArgs) {
DatabaseObject databaseObject = instantiateFromType(); // how to do this?
String tableName = databaseObject.getTableName();
String[] projection = databaseObject.getProjection();
String sortOrder = databaseObject.getDefaultOrderColumn() + " " + DEFAULT_SORT_ORDER;
Cursor cursor = database.query(
tableName,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
return cursor;
}
private DatabaseObject instantiateFromType() {
try {
T interfaceType = (T) type.newInstance();
return interfaceType;
}
catch (Exception e) {
// TODO to handle
}
}
}
这里是你的DogRepository:
public class DogRepository extends MyRepository<Dog> {
public DogRepository() {
super(Dog.class);
}
}
使用Dog实现DatabaseObject:
public class Dog implements DatabaseObject{
//todo
}
回答你的评论。
行DogRepository(Class类型),是否需要传入 作为论证的阶级?
不是不需要(抱歉,我读错了你的评论))。
更进一步,正如您可能注意到的那样,混凝土储存库的构造者是锅炉板代码
如果使用反射来解析DogRepository中使用的泛型背后的类,则不需要为它定义自定义构造函数。
例如,为了检索存储库中使用的类型,Spring使用JDK反射机制使用自己的库来完成这项工作:
Map<TypeVariable, Type> source = GenericTypeResolver.getTypeVariableMap(DogRepository.class);
Spring有它的库,因为它使用了很多反射 但在您的情况下,您也可以在不使用lib但使用自己的实用程序类的情况下完成工作。这是一个从存储库实例中解析泛型类型的示例。
DogRepository dogRepository = new DogRepository();
Class<?> typeClass = (Class<?>) ((ParameterizedType) dogRepository.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println("typeClass=" + typeClass );
使用反射来解析MyRepository
构造函数中的有效泛型类型:
public abstract class MyRepository<T extends DatabaseObject> {
private Class<T> type;
public MyRepository() {
type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
...
}
存储库具体类不再需要自定义构造函数:
public class DogRepository extends MyRepository<Dog> {
}