Проблема в следующем:
AbstractNamedEntityBase entity = service.getByUuid(ref.getUuid());
Эта строка отбрасывает T
.Каждый EntityCloneService работает только с одним подклассом AbstractNamedEntityBase.Для метода getCloneAndSave службы требуется объект типа T
, который является некоторым конкретным подклассом AbstractNamedEntityBase.
Нет способа сохранить универсальный тип значения в вашей карте.Все, что вы когда-либо узнаете об этом, это то, что это 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<>();
.