How to use Generic bounded param in method

Viewed 40

I am trying to write some generic code and facing issue. Here is code

public abstract class AbstractService<D extends IDTO> {
    public String ex(D dto) {
        return null;
    }
}


public class AService extends AbstractService<TestA> {
    @Override
    public String ex(TestA dto) {
        return "a";
    }
}

public class BService extends AbstractService<TestB> {
    @Override
    public String ex(TestB dto) {
        return "b";
    }
}

class TestA impements IDTO {
}

class TestB impements IDTO {
}

So as you can see, its really simple code, one AbstractService with bounded param that extends IDTO. Two implementation of service AService and BService which uses their respective DTO.

Not there is another class that need to call ex() method on basis of runtime instance. here I am facing the problem.

public class TestAll {
    public void executeRequest(final IDTO dto){
        // serviceMap contains list of all Services here A and B
        serviceMap.get(type).ex(dto);
    }
}

Problem on line build().

The method build(capture#5-of ? extends IDTO) in the type AbstractService is not applicable for the arguments (IDTO)

Could someone help to fix this issue?

2 Answers

I found the reason why it was giving me the error. It was my mistake as I was trying to build a map with the help of Spring and was using bounded approach.

It was my previous code.

    @Autowired
    public void setServicesList(List<AbstractService<IDTO>> abstractServices) {
        serviceMap = abstractServices.stream().collect(Collectors.toMap(AbstractService::getType, Function.identity()));
    }

and I had to remove the bounded approach and now it's working.

    public void setServicesList(List<AbstractService> abstractServices) {
        serviceMap = abstractServices.stream().collect(Collectors.toMap(AbstractService::getType, Function.identity()));
    }

In case you know what type of service holds the Map, you could do following:

// define your service map
private final Map<String, AbstractService<? extends IDTO>> serviceMap = Map.of(
        "a", new AService(),
        "b", new BService());

// cast `AbstractServise` from the map into required type:
public void executeRequest(final TestA dto){
    ((AbstractService<TestA>)serviceMap.get("a")).ex(dto);
}

public void executeRequest(final TestB dto){
    ((AbstractService<TestB>)serviceMap.get("b")).ex(dto);
}
Related