我有以下界面:
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。
答案 0 :(得分:1)
在这里,您同时将T
用作生产者和消费者,因此在这里不能使用有界类型参数。您必须像这样使用方法级别的泛型,
public <S> S getCloneAndSave(S existingEntity) throws Exception;
答案 1 :(得分:1)
问题是这样的:
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等。private static final Map<String,EntityCloneService<? extends AbstractNamedEntityBase>> registration = new HashMap<>();
。