【发布时间】:2022-01-08 23:28:31
【问题描述】:
我需要 Java 泛型方面的帮助。 我的模型是:我有一些扩展 Dto(数据传输对象)的类和一些扩展实体的类(我的对象到 DB 的模型)。 我有
interface Mapper<D extends Dto, E extends Entity>{
//Convert a Entity to Dto.
D toDto(E entity);
我有一些实现这个接口的类(即 PersonMapper、BookMapper 等等)。
@Component
public class PersonMapper implements Mapper<PersonDto, PersonEntity> {
//implementation
}
@Component
public class BookMapper implements Mapper<BookDto, BookEntity> {
//implementation
}
我想要做的是使用工厂模式以便在运行时选择我的映射器,这取决于我在输入中传递的字符串。
@Autowired
private PersonMapper personMapper;
@Autowired
private BookMapper bookMapper;
public <D extends Dto, E extends Entity> Mapper<D, E> selectMapper(String entity){
if ("Person".equalsIgnoreCase(entity))
return personMapper;
if("Book".equalsIgnoreCase(entity))
return bookMapper;
...
}
在这种情况下,我有以下编译错误:
Type mismatch: cannot convert from PersonMapper to Mapper<D,E>
我的解决方案:
1)
return (Mapper<D, E>) personMapper;
但我有一个警告:
Type Safety: `Unchecked class from personMapper to Mapper<D,H>`
2)
使用通配符和强制转换b
public Mapper<Dto, Entity> selectMapper(String entity){
Mapper<? extends Dto, ? extends Entity> toReturn = null;
if ("Person".equalsIgnoreCase(entity))
toReturn = personMapper;
else if("Book".equalsIgnoreCase(entity))
toReturn = bookMapper;
...
return (Mapper<Dto, Entity>) toReturn;
}
但在这种情况下,我还有一次警告:
Type safety: Unchecked cast from Mapper<capture#29-of ? extends Dto,capture#30-of ? extends Entity> to Mapper<Dto,Entity>
它有效,但似乎不是一个干净的解决方案
3) 使用通配符作为返回类型:
public Mapper<? extends Dto, ? extends HistoryEntity> selectMapper(String entity)
但你知道,根本不建议使用通配符作为返回类型,也对我没有帮助,因为我想使用这个映射器并调用 mapper.toDto 以确保返回类型是扩展 Dto 的东西。
============================================== =========================
我不解释为什么如果我写一个这样的类构造函数
public Service<D extends Dto, E extends Entity>{
public Service(Mapper<D,E> mapper){
this.mapper = mapper;
}
}
然后我注入(例如)bookMapper 就可以了。
如果 Mapper
============================================== =========================
我请求你的帮助是:
如何使用干净的代码原则(避免编译警告、sonarlint 问题等)编写解决方案以实现这种逻辑?
非常感谢,如果您能抽出一点时间帮助我解决问题,我将不胜感激。
【问题讨论】:
-
这有点像一个经典问题,正如@rzwitserloot 所建议的那样——它正在重新发明一个轮子。无论如何,使用 sting + if-else 链并不是一个好习惯,因此最好将参数
String entity至少替换为Class<? extends Entity> entity并使用class => mapper的映射来查找映射器。但即使这样也不会为您提供足够的运行时类型安全性,因为E和D是不相关的类型。技术上可能存在许多E到D映射器,除非您显式绑定(通过泛型)Entity X到Dto Y
标签: java generics design-patterns factory