Java 我在使用泛型时遇到编译错误
我编写以下代码:Java 我在使用泛型时遇到编译错误,java,generics,Java,Generics,我编写以下代码: public void test() { Callable<?> myCall = new Callable() { @Override public String call() throws Exception { return doDomething(); } }; Callable<?> myCall2 = new Callable() { @Override public St
public void test() {
Callable<?> myCall = new Callable() {
@Override
public String call() throws Exception {
return doDomething();
}
};
Callable<?> myCall2 = new Callable() {
@Override
public String call() throws Exception {
return doDomething2();
}
};
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Future<?>> futuresList = executor.invokeAll((Collection<? extends Callable<?>>) getList());
String result1 = futuresList.get(0).get();
String result2 = futuresList.get(0).get();
...
...
}
private List<Callable<?>> getList() {
.. create callables with wildcard and return them
}
公共无效测试(){
Callable myCall=新的Callable(){
@凌驾
公共字符串调用()引发异常{
返回doDomething();
}
};
可调用myCall2=新可调用(){
@凌驾
公共字符串调用()引发异常{
返回doDomething2();
}
};
ExecutorService executor=Executors.newFixedThreadPool(2);
列表>获取列表(){
..使用通配符创建可调用项并返回它们
}
我得到以下编译错误:类型ExecutorService中的invokeAll(Collection>)方法不适用于参数(Collection>)
编辑
我添加了一个getList方法,因为我希望它使用泛型而不是字符串。
我想了解它为什么不编译。在我的实际程序中,它是一种方法。您必须了解在泛型中何时需要通配符。在您的示例中,您根本不需要通配符。您只在不知道某个泛型对象的类型时才需要通配符。在您的示例中,您希望可调用项返回字符串,以便您可以随时使用r泛型类型,如下所示:
public void test() throws InterruptedException, ExecutionException {
Callable<String> myCall = new Callable<String>(){
public String call() throws Exception{
return doDomething();
}
};
Callable<String> myCall2 = new Callable<String>(){
public String call() throws Exception{
return doDomething2();
}
};
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<String>> list = Arrays.asList(myCall, myCall2);
List<Future<String>> futuresList = executor.invokeAll(list);
String result1 = futuresList.get(0).get();
String result2 = futuresList.get(1).get();
executor.shutdown();
}
您必须了解在泛型中何时需要通配符。在您的示例中,您根本不需要通配符。您只在不知道某个泛型对象的类型时才需要通配符。在您的示例中,您希望可调用项返回字符串,因此应将其用作泛型类型,如下所示:
public void test() throws InterruptedException, ExecutionException {
Callable<String> myCall = new Callable<String>(){
public String call() throws Exception{
return doDomething();
}
};
Callable<String> myCall2 = new Callable<String>(){
public String call() throws Exception{
return doDomething2();
}
};
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<String>> list = Arrays.asList(myCall, myCall2);
List<Future<String>> futuresList = executor.invokeAll(list);
String result1 = futuresList.get(0).get();
String result2 = futuresList.get(1).get();
executor.shutdown();
}
使用
invokeAll()
删除行中的强制转换,并更改未绑定的通配符(?
)使用String
。这不会编译,可能但很难解释确切的原因,但是,既然您真的打算对String
进行操作,只需这样说就可以了。使用invokeAll()
删除行中的强制转换,并更改未绑定的通配符(?
)使用String
。这是不可编译的,可能的,但很难解释确切的原因,但是,既然你真的打算对String
进行操作,那么说出来就行了。我同意其他的答案-你应该只对String
进行参数化,而不是使用通配符
如果你想知道为什么通配符不能像你期望的那样工作,Angelika Langer的优秀Java泛型FAQ有一个章节介绍了这一点(这是第二个例子)。我同意其他的答案-你应该只对
字符串进行参数化,而不是通配符
如果您想知道为什么通配符不能像您期望的那样工作,Angelika Langer的优秀Java泛型FAQ中有一节介绍了这一点(这是第二个示例).我编辑了我的问题。我知道在这个例子中我可以使用字符串。但我的实际程序更通用。我需要使用通配符。我添加了另一个例子。这个例子包括一个强制转换,如果你一直使用泛型,什么不必要。但是,我发现自己偶尔需要一个强制转换,也许其他人会给出一个如何选择的提示对示例进行imize。谢谢。我是否正确理解,我们需要在此处使用泛型而不是通配符,只是因为invokeAll方法是使用泛型而不是通配符编写的?@dan:您必须将通配符类型更多地看作是一种抽象的东西。接收者可能想要表达如下内容“给我一辆车,我不管是汽车还是公共汽车。”这可能写得像Listi编辑了我的问题。我知道在这个例子中我可以使用字符串。但是我的实际程序更通用。我需要使用通配符。我添加了另一个例子。这个例子包括一个强制转换,如果你一直使用泛型,什么应该不是必需的。但是,我发现我自己偶尔需要一个强制转换,也许其他人会提示如何选择请简化示例。谢谢。我是否正确理解,我们需要在此处使用泛型而不是通配符,只是因为invokeAll方法是使用泛型而不是通配符编写的?@dan:您必须将通配符类型更多地看作是一种抽象的东西。接收者可能想要表达如下内容“给我一些车,我不在乎它是汽车还是公共汽车。”这可能写得像“列表我编辑了问题。我不打算只使用字符串。我编辑了问题。我不打算只使用字符串。