有没有解决我的问题使用泛型? [英] Is there a solution to my problem using generics?

查看:81
本文介绍了有没有解决我的问题使用泛型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用java.util.concurrency框架来实现一些代码。我将传递一个可调用的集合到一个并行执行它们的类中。我试图找出以安全的方式获得每个回应的最佳方式。以下是一些代码,以帮助解释我在做什么:



首先创建我的可调用的工作要平行调用。例如,这里第一个工作单元返回一个 String ,第二个单元 Integer

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

可调用<整数> secondCallable = new Callable< Integer>(){
public Integer call(){...}
};

现在我把它们引入我的框架来并行运行它们,适当的响应对象。这是一个有效的实现:

  Map< Callable,Object> responseMap = ParallelSender.send(firstCallable,
secondCallable);

其中对象是一个特定的可赎回。因此,您可以这样做:

  String firstCallableResponse =(String)responseMap.get(firstCallable); 
整数secondCallableResponse =(整数)responseMap.get(secondCallable);

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

  Map< Callable&T; T> responseMap = ParallelSender.send(...); 
String firstCallableResponse = responseMap.get(firstCallable);

,这样返回的值是基于 Callable 键。我担心的是,如果有人将工作单位的返回类型重新设计(从 Integer BigDecimal 那么来自 Object 的转换将永远不会被自动重构工具所捕获,并可能导致运行时问题。






结论:感谢下面所有有用的评论和讨论,我已经采取了一个稍微不同的手法(尽管如此,对于我上面的问题,Sean Patrick Floyd也是如此)。我最后完全删除响应图,并填充 Callable 对象与响应。以下是相关的代码片段:

  public abstract class AbstractParallelCallable< V>实现Callable< V> {

/ **此类的Call方法生成的响应。 * /
private V callableResponse;

public V getResponse(){
return callableResponse;
}

public void setResponse(V response){
callableResponse = response;
}
}

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

  for(ParallelFutureTask< Object> future:期货){
try {
future.getCallableHandle()。setResponse(future.get());
} catch(例外e){...}
}

其中getCallableHandle通过提供对Callable对象的引用返回AbstractParallelCallable对象和ParallelFutureTask包装FutureTask。执行后,调用代码可以这样做:

 整数theResult = firstCallable.getResponse(); 


解决方案

基于方法的方法



唯一的方法是将其封装在一个方法中:

  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);
}

}



客户端代码



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

  ParallelSender parallelSender = new ParallelSender ); 
可调用<整数> integerCallable = new Callable< Integer>(){

@Override
public Integer call()throws异常{
return Integer.valueOf(1);
}
};
整数result = parallelSender.getResult(integerCallable);


I'm implementing some code using the java.util.concurrency framework. I will be passing a collection of callables to a class which will execute them in parallel. I'm trying to work out the best way of getting a hold of each response in a type safe manner. Here's some code to help explain what I'm doing:

First I create my Callables, which are units of work to be called in parallel. For example, here the first unit of work returns a String and the second an Integer:

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

Callable<Integer> secondCallable = new Callable<Integer>(){
   public Integer call() {...}
};

Now I fire them into my framework to run them in parallel and the trick is getting a handle to the appropiate response Object. Here's an implementation that works:

Map<Callable,Object> responseMap = ParallelSender.send(firstCallable, 
                                                       secondCallable);

where Object is the response of a particular Callable. Thus, you can do this:

String firstCallableResponse = (String)responseMap.get(firstCallable);
Integer secondCallableResponse = (Integer)responseMap.get(secondCallable);

So my question is, is it possible to avoid casting when fetching from the Map? This doesn't compile, but I'm thinking along these lines:

Map<Callable<T>, T> responseMap = ParallelSender.send(...);
String firstCallableResponse = responseMap.get(firstCallable);

such that the value returned is based on the typed parameter of the Callable key. My concern is that if anyone refactors the return type of the unit of work (say from Integer to BigDecimal or whatever) then the cast from Object will never be caught by automatic refactor tools and could lead to runtime issues.


CONCLUSION: Thanks to all the helpful comments and discussion below, I have taken a slightly different tact (though credited Sean Patrick Floyd with a correct to my question above). I ended up dropping the response map alltogether and populating the Callable object with the response. Here are the relevant code snippets:

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;
   }
}

Thus, I have an abstract implementation which wrappers the Callable object by storing the response. Next,in my parallel processing I get the response each Future created and populate the AbstractParallelCallable:

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

where getCallableHandle returns the AbstractParallelCallable object and ParallelFutureTask wrappers FutureTask by providing a reference to the Callable object. After execution, the calling code can then do this:

Integer theResult = firstCallable.getResponse();

解决方案

Method-based approach

The only way you can do it is to encapsulate it in a method:

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);
    }

}

Client code

Now your client code does not need to cast:

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);

这篇关于有没有解决我的问题使用泛型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆