考虑以下代码:
public abstract class MyObject {
}
public interface Dao<T extends MyObject> {
}
public abstract class JsonDao<T extends MyObject> implements Dao<T> {
}
public abstract class SqliteDao<T extends MyObject> implements Dao<T> {
}
public interface DaoFactory<*????*> {
public *????* getDao(Class<? extends MyObject> objectClass);
}
现在我想要的是getDao能够实例化JsonDao和SqliteDao,但是通过扩展MyObject的类进行参数化,基本上是这样的:
public interface DaoFactory<T<? extends MyObject> extends Dao<? extends MyObject>> {
public <U extends MyObject> T<U> getDao(Class<U> objectClass);
}
类似的事情是否可能发生,还是类型擦除阻止了它?
最佳答案
您可以声明DaoFactory
如下:
public interface DaoFactory<D extends Dao<? extends MyObject>> {
<T extends MyObject> D getDao(Class<T> type);
}
然后,
JsonDaoFactory
可以实现如下:public class JsonDaoFactory implements DaoFactory<JsonDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, JsonDao<? extends MyObject>> daos =
new HashMap<>();
public JsonDaoFactory() {
daos.put(Contact.class, new JsonContactDao());
daos.put(Customer.class, new JsonCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> JsonDao<T> getDao(Class<T> type) {
return (JsonDao<T>) daos.get(type);
}
}
我使用了
Map
来使MyObject
的每个后代与其对应的JsonDao
匹配(在这里,我分别使用了Contact
和Customer
以及JsonContactDao
和JsonCustomerDao
)。我取消了未选中的强制转换警告,因为我在构造函数中明确填充了地图,因此我确定不会有ClassCastException
。为了完整起见,下面是
SqliteDaoFactory
的代码:public class SqliteDaoFactory implements DaoFactory<SqliteDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, SqliteDao<? extends MyObject>> daos =
new HashMap<>();
public SqliteDaoFactory() {
daos.put(Contact.class, new SqliteContactDao());
daos.put(Customer.class, new SqliteCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> SqliteDao<T> getDao(Class<T> type) {
return (SqliteDao<T>) daos.get(type);
}
}
两个工厂的代码几乎都是重复的,但是我找不到解决此问题的方法。
这是使用这些工厂的方法:
JsonDaoFactory jsonDaoFactory = new JsonDaoFactory();
JsonDao<Contact> contactJsonDao = jsonDaoFactory.getDao(Contact.class);
JsonDao<Customer> customerJsonDao = jsonDaoFactory.getDao(Customer.class);
SqliteDaoFactory sqliteDaoFactory = new SqliteDaoFactory();
SqliteDao<Contact> contactSqliteDao = sqliteDaoFactory.getDao(Contact.class);
SqliteDao<Customer> customerSqliteDao = sqliteDaoFactory.getDao(Customer.class);
关于java - Java泛型类型参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44461784/