Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

generics

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 compilator 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 generic types extend Object, so I don't see where the problem is?

We are trying to preserve an interface. This is the original method of the interface:

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

I tweaked it a little bit so that the classes that use the interface don't get affected:

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

Basically, we are mapping Pojo's, we've been using DozerMapper, but now, the major architect wants compile time safety, and the DozerMapper isn't. For example if a pojo's field gets updated (renamed, deleted) we need to manually update the xml, that describes the mapping between the pojo's (the xml is used in case of nontrivial mapping, for example, when the names of fields of the pojo's don't correspond completely, which is often the case)

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

like image 988
Daniel Rusev Avatar asked Nov 25 '14 17:11

Daniel Rusev


1 Answers

The getClass method returns Class<?> and not Class<S>, as I think you are expecting. See Object#getClass in the API.

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

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

You know source class is S so I think you can safely add a cast, but you will get a warning:

CopyMapper<S, D> copyMapper = mapperFactory.getMapper((Class<S>)source.getClass(), destinationClass);
like image 160
Tobías Avatar answered Sep 17 '22 16:09

Tobías