Proper use of unbounded wilcard generics

主宰稳场 提交于 2020-01-06 04:31:09

问题


I'm trying to use unbounded wildcards because I have some Callable's that return an Object but I'm not interested in the object (they return null and I'm just using Callable instead of Runnable to be able to throw checked Exceptions).

So in principle I want to do this:

CompletionService<?> ecs = ...
Callable<?> = ...
Future<?> f = ecs.submit(c);

But here I get an error saying:

The method submit(Callable<capture#1-of ?>) in the type CompletionService<capture#1-of ?> is not applicable for the arguments (Callable<capture#2-of ?>)

Later on I just want to call f.get() to handle exceptions thrown in the submitted task.

So what is the proper way to handle this?


回答1:


Wildcards are not appropriate here. (Also note that if you have two wildcards they don't match as such, just as if you have generic parameters named T and U.)

The standard approach is to use <Void>.




回答2:


try this

    CompletionService<Object> ecs = ...;
    Callable<Object> c = ...;
    Future<?> f = ecs.submit(c);



回答3:


The problem here is that ? is not an identifier. It means "something unknown." The first "something unknown" is not the same that the second one. By other words think that you want to submit Callable<C> to CompletionService<S>. Obviously it cannot work.

The way to solve this is either use Object as a generic type:

CompletionService<?> ecs = ...
Callable<?> = ...
Future<?> f = ecs.submit(c);

or, probably better, define your own type T on method level and use it in your code:

<T> void foo() {
    CompletionService<T> ecs = ...
    Callable<T> = ...
    Future<?> f = ecs.submit(c);
}

you will probably get warining in line CompletionService<T> ecs = ..., but you can suppress it (only here). The rest of the code should be OK.

This recommendation however does not sound like a good practice. Generics have been added to the java programming language exactly to solve the problem of unknown types. So, better way is to use generics correctly in whole your code.




回答4:


You need a type variable in order to declare that the type parameters of all objects match, even if you are not interested in the type itself. In order to declare a type variable, you have to put the code inside a method or constructor which can declare it, e.g.

static <T> Future<T> doIt(Callable<T> c, Executor e) {
  CompletionService<T> ecs = new ExecutorCompletionService<T>(e);
  return ecs.submit(c);
}

Now you can even call it with wildcards:

Callable<?> c;
Executor e;
Future<?> f=doIt(c, e);


来源:https://stackoverflow.com/questions/18483833/proper-use-of-unbounded-wilcard-generics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!