java - 将泛型转换为子类型

标签 java generics casting

这是后续:my previous question

我的以下代码行不起作用:

IAccount account = (AccountModel) new AccountRepository().getByEmail(emailaddress);

...getByEmail(...)的返回类型是 Model<Account> ,和AccountModel延伸Model<Account> .
但我得到了 java.lang.ClassCastException: models.Model cannot be cast to models.AccountModel当我测试它时。我知道这是因为每个 AccountModelModel<Account> ,但反之则不然。
有什么方法可以确保我可以解决这个问题(或解决它)。

public class AccountRepository extends Repository<Account> {

    public AccountRepository() {
        super(Account.class);
    }

    public Model<Account> getByEmail(String emailAddress) {
        return this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'");
    }
}

public abstract class Repository<T> implements Serializable {
    protected final Model<T> getCustomHqlSingle(String hql) {
        List<Model<T>> t = this.getCustomHqlList(hql);
        if (t != null && !t.isEmpty()) {
            return t.get(0);
        } else {
            return null;
        }
    }

    protected final List<Model<T>> getCustomHqlList(String hql) {

        Session session = SESSION_FACTORY.openSession();

        try {
            session.beginTransaction();
            List<T> entities = session.createQuery(hql).getResultList();
            List<Model<T>> result = new ArrayList<>();
            for (T t : entities) {
                result.add(this.getByEntity(t));
            }
            return result;
        } finally {
            session.close();
        }
}
<小时/>

对于将此问题标记为重复的人,让我改写我的问题中的以下句子:

I know this is because every AccountModel is a Model<Account>, but not the other way around.

I know this is because every Dog is an Animal, but not the other way around.

最佳答案

您必须设计一种方法来转换 Model<Account>AccountModel 。从您的其他问题中获取代码,您可以为此添加一个构造函数到 AccountModel类:

public class AccountModel extends Model<Account> implements IAccount {
    private static final AccountRepository REPOSITORY = new AccountRepository();

    public AccountModel(Account entity) {
        super(entity, REPOSITORY);
    }

    public AccountModel(Model<Account> model) { // <---
        super(model._entity, REPOSITORY);
    }

    // Method implementations...
}

然后更改您的AccountRepository返回 AccountModel 的类来自getByEmail :

public AccountModel getByEmail(String emailAddress) {
    return new AccountModel(this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'"));
}

它使用新的构造函数来转换 Model<Account>AccountModel .

<小时/>

还有另一种选择。而不是打电话new Model<T>(...)Repository ,您可以让实现类实现一个抽象方法,该方法将返回所需的 Model类型:

public abstract class Repository<T, R> implements Serializable

...

public Repository(Class<T> repositoryClass) {

    if (!Repository._initiated) 
        setup();

    this.cons = cons;
}

protected abstract R getModel(T entity, Repository<T> repo); // <--

然后在工厂方法中的某个地方:

public R getByFoo(...) {
   ...
   T t = session.get(_repositoryClass, ...);
   return getModel(t, this);
}

哪里AccountRepository将返回一个新的 AccountModel :

public class AccountRepository extends Repository<Account, AccountModel> {

    public AccountRepository() {
        super(Account.class);
    }

    @Override
    protected AccountModel getModel(Account entity, Repository<Account> repo) {
        return new AccountModel(entity);
    }

}

关于java - 将泛型转换为子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41462388/

相关文章:

c++ - 是否可以将对象转换为不相关的类?

swift - 如何将 AnyKeyPath 转换为 WritableKeyPath?

java - 为什么我的 Bit String to Hex String 代码没有打印出结果?

java - 如何实时连接Java和Flex?

c# - "Elegant"从对象的 List<T> 中获取属性值列表的方法?

c# - 如何检查 IEnumerable<T> 中的 T 是否为接口(interface)?

PHP 将 float 转换为 int 类型的意外结果

java - JAVA 中的 Streams 聚合,这是一个好方法吗?

java - 打印出小于给定数 N 的素数

java - 静态类/接口(interface)的 Guice 泛型配置错误