java - Java Generic 如何转换为子类型以调用泛型方法
问题描述
我有以下界面:
public interface EntityCloneService<T extends AbstractNamedEntityBase> {
/**
* Given a UUID load the Entity Type.
*
* @param uuid
* @return Entity From DB and
*/
public T getByUuid(UUID uuid);
/**
* Given the Existing Entity, clone it and save in DB, then return clone instance.
*/
public T getCloneAndSave(T existingEntity) throws Exception;
}
现在我有通用服务,我有
@Component
public class GenericEntityCloneService {
private static final Map<String,EntityCloneService<? extends AbstractNamedEntityBase>> registration =
new HashMap<String,EntityCloneService<? extends AbstractNamedEntityBase>>(); // here we have registration of all entity by name to service actual implementation.
public void clone(AbstractNamedEntityBase existingEntity) {
EntityCloneService<? extends AbstractNamedEntityBase> service = registration.get("SOME KEY");
AbstractNamedEntityBase entity = service.getByUuid(ref.getUuid()); // THIS WORKS because it up casting.
service.getCloneAndSave(entity); // now how do I pass entity object such that
}
}
当我尝试编译此代码时无法编译。我知道 getCloneAndSave() 我正在传递不允许的类型 AbstractNamedEntityBase。那么如何拨打电话 service.getCloneAndSave(entity); 任何帮助是极大的赞赏。我正在使用java 8。
解决方案
问题是这样的:
AbstractNamedEntityBase entity = service.getByUuid(ref.getUuid());
那条线丢弃T
。每个 EntityCloneService 都与 AbstractNamedEntityBase 的一个子类一起工作。该服务的 getCloneAndSave 方法需要一个类型为 的对象T
,它是AbstractNamedEntityBase的某个特定子类。
无法在 Map 中保留值的通用类型。你所知道的只是它是一个EntityCloneService<? extends AbstractNamedEntityBase>
. 但是,您可以通过一些选项来解决它。
最简单的方法是在 EntityCloneService 中添加一个默认方法。在该接口内部,T
是已知的,无需直接引用 AbstractNamedEntityBase:
default T getCloneAndSaveFor(UUID uuid)
throws Exception {
T entity = getByUuid(uuid);
return getCloneAndSave(entity);
}
另一种可能性是在 GenericEntityCloneService 中编写一个单独的方法,该方法知道每个 EntityCloneService 具有特定类型,即使该特定类型本身不知道:
private <E extends AbstractNamedEntityBase> E getCloneAndSaveFor(
UUID uuid,
EntityCloneService<E> service)
throws Exception {
E entity = service.getByUuid(uuid);
return service.getCloneAndSave(entity);
}
旁注:
throws Exception
不是一个好习惯。不要强制调用者捕获旨在暴露程序员错误的未经检查的异常,例如 NullPointerException、IndexOutOfBoundsException、IllegalArgumentException 等。- 您可以将 Map 声明缩短为
private static final Map<String,EntityCloneService<? extends AbstractNamedEntityBase>> registration = new HashMap<>();
.
推荐阅读
- swift - 视图第二次出现后,Swift UITableView cellForRowAt indexPath 不会在 tableView.reloadData() 上被调用
- amazon-web-services - AWS Amplify 和 Vue 路由器历史模式
- java - 使用改造方法从服务器获取数据
- orocommerce - orocommerce 4.1 中如何实现最小起订量?
- c++ - 为什么打印 16 而不是 17 并且变量不递增?
- uwp - 如何取消下载操作?
- powershell - 运行 powershell --version 时出现错误
- arrays - Kotlin:在一维数组上做数学运算
- php - Facebook 和 Google 登录的代码无法在实时服务器上运行
- android - 如何显示在 RecyclerView 内的滚动条中移动的文本?