ModelMapper: How to map to a List of generic instances of known concrete type

Viewed 1047

I want to convert with the ModelMapper a List<> to a List<T> knowing the exact java.lang.Class of T. But the ModelMapper keeps only instantiating the common parent class of T...

for your context: I want to convert a list of DTO to a list of Domain, but as I do it in every Service class I extracted it in a generic abstract Service.

public class BaseClass {}
public class SubClass1 extends BaseClass {}

public <T extends BaseClass> List<T> getList(Class<T> specificClass) {
    ...
    Type listType = new TypeToken<List<T>>(){}.getType(); // here problem

    List<T> responseList = modelMapper.map(listIAlreadyHave, listType);

    return responseList;
}

List<SubClass1> list = doIt(SubClass1.class);

Inspiration here

I would like list to be a list of SubClass1 instances, but i get only BaseClass instances. I don't blame Java for not understading my listType definition because T is unknown on runntime, but how can i use the specificClass parameter i generously provide?

Thank you dear community!

2 Answers

When the generic method is called, types are already erased and TypeToken captures a generic List<T> type.

The method is defined with T extends BaseClass and that's why the conversion is done to this class. If you remove the extends, it will convert your data class to itself.

One way to solve your issue is to capture the type before erasure: that can be done before calling the generic method.

public class BaseClass {}
public class SubClass extends BaseClass {}
public class OtherClass {}

public <T extends BaseClass> List<T> getList(Type listType, List<?> listIAlreadyHave) {
    return new ModelMapper().map(listIAlreadyHave, listType);
}

List<OtherClass> listIAlreadyHave = buildList();

// Capture type before erasure
Type listType = new TypeToken<List<SubClass>>() {}.getType();

List<SubClass> list = getList(listType, listIAlreadyHave);;

You can use explicit mapping and specify the way mapper has to convert one instance to another. Didn't you meant to make SubClass1 extend BaseClass? If you meant to you could just take advantage of polymorphism.

Have a good day!

Related