mohit
mohit

Reputation: 6044

Method returns object instead of type explicitly casted in generics method

I was trying to get my head around generics of java. And it seems difficult to implement what I want.

I want to make a generic task aggregator. Meaning, given a list of request, I need to process each request through some handler (that is obtained from a factory based on request). And return the list of response. Now to speed up the process, I want to obtain the results by executing handlers in parallel.

First I've define a interface THandler:

interface THandler<Request, Response> {
        Response handle(Request request);
}

This is my aggregator:

public class AggTasks
{
    public static <Request, Response> long aggregate(List <Request> req, List <Response> res) {

        CountDownLatch allDone = new CountDownLatch(req.size());
        List <TWork<Request, Response>> workers = new ArrayList<>();
        for (Request r : req) {
            // Getting error: The constructor TWork<Request,Response>(THandler<Request,Object>, Request, CountDownLatch) is undefined
            workers.add(new TWork<Request, Response>(getHandler(r), r, allDone));
        }

        for (TWork<Request, Response> w : workers) {
            new Thread(w).start();
        }
        allDone.await();
        for (TWork<Request, Response> w : workers) {
            res.add(w.collectResponse());
        }

        return 0;
    }
}

This is my TWork:

class TWork<Request, Response> implements Runnable{

        private THandler<Request, Response> handler;
        private Request request;
        private Response response;

        public TWork(THandler<Request, Response> tHandler, Request r, CountDownLatch allDone)
        {
            this.handler = tHandler;
            this.request = r;
        }

        public Response collectResponse() {
            return response;
        }

        @Override
        public void run()
        {
            response = handler.handle(request);
        }

    }

Finally here is getHandler() and FactoryHandler. I tried explicitly casting the return value to THandler<Request, Response>, however, still at compile time it's showing as THandler<Request,Object>:

    @SuppressWarnings("unchecked")
    private static <Request, Response> THandler<Request, Response> getHandler(Request req) {
        return (THandler<Request, Response>) FactoryHandler.getHandler(req);
    }

    class FactoryHandler {

        @SuppressWarnings("unchecked")
        public static <Request, Response> THandler<Request, Response> getHandler(Request req) {
            return (THandler<Request, Response>) new StringHandler();
        }
    }

Any suggestions to improve the design is welcome.

Edit:
I tried the suggestion of Wietlol: and it seems to work if I skip call to static method getHandler():

workers.add(new TWork<Request, Response>(FactoryHandler.<Request, Response>getHandler(r), r, allDone));

Upvotes: 0

Views: 63

Answers (1)

Wietlol
Wietlol

Reputation: 1071

FactoryHandler.getHandler(req);

Only defines the type of "Request", implicitly defined by the type of "req". Response is not defined and thus predicted as Object to make it work with everything.

The easiest solution would be to call "getHandler()" like this:

FactoryHandler.<Request, Response>getHandler(req);

Which explicitly defines the generic types.

Upvotes: 2

Related Questions