我的以下代码行不起作用:
IAccount account = (AccountModel) new AccountRepository().getByEmail(emailaddress);
...getByEmail(...)
的返回类型为Model<Account>
,AccountModel
延伸Model<Account>
。
然而,当我测试时,我得到java.lang.ClassCastException: models.Model cannot be cast to models.AccountModel
。我知道这是因为每个AccountModel
都是Model<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();
}
}
对于将此问题标记为重复的人,让我从我的问题中重新措辞以下句子:
我知道这是因为每个
AccountModel
都是Model<Account>
,但是 不是相反。
要
我知道这是因为每个
Dog
都是Animal
,而不是另一个public abstract class BaseConnection<T> { protected T _stream; protected TcpClient _client; public abstract void Connect(); public abstract void Disconnect(); } public class Connection<T> : BaseConnection<T> where T: Stream { public override void Connect(){/*Do somthing*/} public override void Disconnect(){/*Do somthing*/} public void Reconnect() { Disconnect(); Connect(); } }
四处走动。
答案 0 :(得分:1)
您必须设计一种方法,将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);
}
}
答案 1 :(得分:0)
既然你说你理解为什么会出现错误,那么让我试着解释一下有关投射的其他内容。
除了一些有限的情况,铸造操作员不会更改正在施放的物品。 Casting只是对编译器的指令,说&#34;我的逻辑保证了转换对象的类型与编译器可以确定的不同,所以当你(编译器)告诉我这是一个错误时,我是确定,在运行时,它会没事的。所以不要给我一个错误&#34;。
它没有说&#34;把这个对象转换成另一个类似的对象&#34;。感谢天堂,这种操作在Java中是不可能的。