泛型:无法将<capture#1-of ? extends Object,D>转换为<S,D>。

11
我有以下类结构:
public interface CopyMapper<S, D> {
    public D map(S sourceObject);
}

public interface CopyMapperFactory {
    public <S, D> CopyMapper<S, D> getMapper(Class<S> sourceClass, Class<D> destinationClass);
}

public class Mapper {
    public <S, D> D map(S source, Class<D> destinationClass) {
        //This is where I get compile time error
        CopyMapper<S, D> copyMapper = mapperFactory.getMapper(source.getClass(), destinationClass);
        return copyMapper.map(source);
    }

我的Eclipse编译器出现了以下错误:
Type mismatch: cannot convert from CopyMapper<capture#1-of ? extends Object,D> to CopyMapper<S,D>

据我所知,所有泛型类型都扩展自Object,所以我不知道问题出在哪里?
我们正在努力维护一个接口。这是该接口的原始方法:
<T> T map(Object source, Class<T> destinationClass)

我稍微修改了一下,以便不影响使用该接口的类:

<S, D> D map(S source, Class<D> destinationClass);

基本上,我们正在映射POJO对象,我们一直在使用DozerMapper,但现在,主要架构师想要编译时安全性,而DozerMapper并没有。例如,如果POJO字段得到更新(重命名、删除),我们需要手动更新描述POJO之间映射的xml文件(在映射不是简单一一对应的情况下使用xml文件,例如当POJO字段名称不完全对应时,这种情况经常发生)。
现在,我们有复制类,数百个,每个类都用于映射两个POJO之间的关系。我们试图使用工厂设计模式,根据源类和目标类返回特定的映射器类(实现CopyMapper接口)。

它只是编译而已。为什么?你认为它不应该吗? - Daniel Rusev
为什么你要传递Class<S>?你不能只传递S吗? - Seb
那么我就必须将其转换为特定类型,这不是编译时安全的。 - Daniel Rusev
如果您更新了字段名称,那么是的,您还必须调整XML配置。这些是否都是两个POJO之间的直接映射,无需任何自定义?在重命名后,这些POJO是否具有相同的字段名称?或者您是否正在使用CustomConverter(当您真正应该使用DozerConverter)? - Makoto
我对此并不十分确定。Dozer在其所做的事情方面表现相当出色;如果你对速度有所要求,你需要使用分析器来验证它。除此之外,你还没有完全回答我的问题 - 我理解你想要类型安全的动机,但在什么情况下你正在尝试获得它?你正在进行哪种映射,绝对需要它?是否有“CustomConverter”潜伏? - Makoto
显示剩余4条评论
1个回答

8
getClass方法返回Class<?>而不是您所期望的Class<S>。请参见API中的Object#getClass

由于它返回Class<?>,您会丢失类型信息,因此实际上是这样的:

CopyMapper<?, D> copyMapper = mapperFactory.getMapper(source.getClass(), destinationClass);

您知道源类是S,所以我认为您可以安全地进行强制转换,但您将会收到一个警告:

CopyMapper<S, D> copyMapper = mapperFactory.getMapper((Class<S>)source.getClass(), destinationClass);

那么这是一个安全的转换,因为我确定source的类是 S,对吧? - Daniel Rusev
1
如果这只是一个泛型问题,我会认为你是对的。但我怀疑他们在使用Dozer时存在更深层次的问题。 - Makoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接