Generics: cannot convert from <capture # 1-of? extends Object, D> to <S, D>

I have the following class structure:

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); } 

My Eclipse compiler gives me the following error:

 Type mismatch: cannot convert from CopyMapper<capture#1-of ? extends Object,D> to CopyMapper<S,D> 

As far as I know, all type types are extended by Object , so I don’t see where the problem is?

We are trying to save the interface. This is the original interface method:

 <T> T map(Object source, Class<T> destinationClass) 

I changed it a bit so that classes using the interface do not suffer:

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

Basically, we map Pojo, we use DozerMapper, but now the chief architect wants to save time during compilation, and DozerMapper does not. For example, if the pojo field is updated (renamed, deleted), we need to manually update the xml that describes the mapping between pojo (xml is used in case of nontrivial matching, for example, when the names of pojo fields do not match completely, which often happens)

Now we have copy classes, hundreds of them, one for each mapping between pojo. We are trying to use Factory Design patter to return a specific mapper class (implementing the CopyMapper interface) based on the source class and the target class.

+6
source share
1 answer

The getClass method returns Class<?> , Not Class<S> , as I think you expect. See Object#getClass in the API.

When it returns Class<?> , You lose type information, so you really have this:

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

You know that the original class is S , so I think you can safely add a throw, but you will get a warning:

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

Source: https://habr.com/ru/post/978693/


All Articles