使用泛型是否有解决我的问题的方法?

Chr*_*ght 3 java generics map

我正在使用java.util.concurrency框架实现一些代码.我将把一组callables传递给一个将并行执行它们的类.我正试图找出以类型安全的方式获取每个响应的最佳方法.这里有一些代码可以帮助解释我在做什么:

首先我创建我的Callables,这是要并行调用的工作单元.例如,这里第一个工作单元返回a String,第二个工作单元返回Integer:

Callable<String> firstCallable = new Callable<String>(){
   public String call() {...}
};

Callable<Integer> secondCallable = new Callable<Integer>(){
   public Integer call() {...}
};
Run Code Online (Sandbox Code Playgroud)

现在我将它们激活到我的框架中以并行运行它们,并且诀窍是获得适当的响应对象的句柄.这是一个有效的实现:

Map<Callable,Object> responseMap = ParallelSender.send(firstCallable, 
                                                       secondCallable);
Run Code Online (Sandbox Code Playgroud)

Object特定的响应在哪里Callable.因此,你可以这样做:

String firstCallableResponse = (String)responseMap.get(firstCallable);
Integer secondCallableResponse = (Integer)responseMap.get(secondCallable);
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,从地图中获取时是否可以避免投射?这不会编译,但我正在考虑这些方面:

Map<Callable<T>, T> responseMap = ParallelSender.send(...);
String firstCallableResponse = responseMap.get(firstCallable);
Run Code Online (Sandbox Code Playgroud)

这样返回的值基于Callable键的类型参数.我担心的是,如果有人refactors工作单位的返回类型(从说IntegerBigDecimal,然后自投或其他)Object永远不会被自动重构工具被捕获,并可能导致运行时问题.


结论:感谢下面的所有有用的评论和讨论,我采取了一个略有不同的机智(尽管肖恩帕特里克弗洛伊德认为上面的问题是正确的).我最终完全删除了响应映射并Callable用响应填充了对象.以下是相关的代码段:

public abstract class AbstractParallelCallable<V> implements Callable<V> {

   /** The response generated by the Call method of this class. */
   private V callableResponse;

   public V getResponse() {
       return callableResponse;
   }

   public void setResponse(V response) {
       callableResponse = response;
   }
}
Run Code Online (Sandbox Code Playgroud)

因此,我有一个抽象实现,它通过存储响应来包装Callable对象.接下来,在我的并行处理中,我得到每个Future创建的响应并填充AbstractParallelCallable:

for (ParallelFutureTask<Object> future : futures) {
   try {
      future.getCallableHandle().setResponse(future.get());
   } catch(Exception e) {...}
}
Run Code Online (Sandbox Code Playgroud)

其中getCallableHandle返回AbstractParallelCallable对象,ParallelFutureTask通过提供对Callable对象的引用来包装FutureTask.执行后,调用代码可以执行以下操作:

Integer theResult = firstCallable.getResponse();
Run Code Online (Sandbox Code Playgroud)

Sea*_*oyd 8

基于方法的方法

你能做到的唯一方法是将它封装在一个方法中:

class ParallelSender{

    private final Map<Callable<?>, Object> map =
        new HashMap<Callable<?>, Object>();

    @SuppressWarnings("unchecked")
    public <T> T getResult(final Callable<T> callable){
        return (T) map.get(callable);
    }

}
Run Code Online (Sandbox Code Playgroud)

客户代码

现在您的客户端代码不需要强制转换:

ParallelSender parallelSender = new ParallelSender();
Callable<Integer> integerCallable = new Callable<Integer>(){

    @Override
    public Integer call() throws Exception{
        return Integer.valueOf(1);
    }
};
Integer result = parallelSender.getResult(integerCallable);
Run Code Online (Sandbox Code Playgroud)