简体   繁体   English

Java泛型类型参数

[英]Java generics type parameters

Consider the following code: 考虑以下代码:

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);
}

Now what I'd like is for getDao to be able to instanciate both JsonDao and SqliteDao, but parametrized with a class extending MyObject, basically something like this: 现在我想要的是getDao能够实例化JsonDao和SqliteDao,但是通过扩展MyObject的类进行参数化,基本上是这样的:

public interface DaoFactory<T<? extends MyObject> extends Dao<? extends MyObject>> {
    public <U extends MyObject> T<U> getDao(Class<U> objectClass);
}

Is something similar even possible or does type erasure prevent it? 类似的事情是否可能发生,还是类型擦除阻止了它?

Does this fit your needs? 这符合您的需求吗?

public interface DaoFactory<O extends MyObject, D extends Dao<O>> extends Dao<O> {
    public D getDao(Class<O> objectClass);
    //or for any subclass
    public <RO extends O, RD extends D<RO>> RD getSubDao(Class<RO> objectSubclass);

    //or maybe this
    public <RO extends O> Dao<RO> getSimpleSubDao(Class<RO> objectSubclass);
}

You could declare DaoFactory as follows: 您可以声明DaoFactory如下:

public interface DaoFactory<D extends Dao<? extends MyObject>> {

    <T extends MyObject> D getDao(Class<T> type);
}

Then, JsonDaoFactory could be implemented as follows: 然后,可以如下实现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);
    }
}

I've used a Map to make every descendant of MyObject match its corresponding JsonDao (here I've used Contact and Customer , and JsonContactDao and JsonCustomerDao , respectively). 我使用Map使MyObject每个后代与其对应的JsonDao匹配(这里我分别使用ContactCustomer ,以及JsonContactDaoJsonCustomerDao )。 I've suppressed an unchecked cast warning because I'm explicitly filling the map in the constructor, so I'm sure there won't be a ClassCastException . 我取消了未选中的强制转换警告,因为我在构造函数中明确填充了地图,因此我确定不会出现ClassCastException

For completeness, here's the code for SqliteDaoFactory : 为了完整SqliteDaoFactory ,这是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);
    }
}

The code for both factories is almost duplicated, but I couldn't find a way to solve this. 两个工厂的代码几乎都是重复的,但是我找不到解决此问题的方法。

Here's how to use these factories: 这是使用这些工厂的方法:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM