Java 实际参数列表<&书信电报;匿名可调用<;字符串>&燃气轮机&燃气轮机;无法转换为列表<;可调用<;字符串>&燃气轮机;按方法调用转换

Java 实际参数列表<&书信电报;匿名可调用<;字符串>&燃气轮机&燃气轮机;无法转换为列表<;可调用<;字符串>&燃气轮机;按方法调用转换,java,generics,Java,Generics,我创建了一个静态类方法(这里称为“函数”)f,它获取一个可调用的列表: 这很奇怪。似乎在说一个表达式(产生一个值)是一个类型。使用javac时会出现不同的错误: A.java:11: error: method f in class A cannot be applied to given types; f(s(new Callable<String>() { ^ required: List<Callable<String>> fou

我创建了一个静态类方法(这里称为“函数”)
f
,它获取一个
可调用的
列表:

这很奇怪。似乎在说一个表达式(产生一个值)是一个类型。使用javac时会出现不同的错误:

A.java:11: error: method f in class A cannot be applied to given types;
    f(s(new Callable<String>() {
    ^
  required: List<Callable<String>>
  found: List<<anonymous Callable<String>>>
  reason: actual argument List<<anonymous Callable<String>>> cannot be converted to List<Callable<String>> by method invocation conversion
1 error
A.java:11:错误:类A中的方法f不能应用于给定的类型;
f(s)(新的可调用(){
^
必填项:列表
找到:列表
原因:实际参数列表无法通过方法调用转换转换为列表
1错误

错误消息有点误导。我猜是这样的,因为编译器尚未给匿名类型命名(或选择不使用它)。但基本上,
列表
不是
列表
的子类型,因此不是期望后者的方法的有效参数。

错误消息有点误导。我猜是这样的,因为编译器尚未为匿名类型指定名称(或选择不使用它)。但基本上,
列表
不是
列表
的子类型,因此不是期望后者的方法的有效参数。

f
的签名更改为具有上限的
可调用

static void f(List<? extends Callable<String>> l) {}

static void f(List更改
f
的签名,使其上限为
Callable

static void f(List<? extends Callable<String>> l) {}

static void f(ListThis为我编译…将代码复制/粘贴到Eclipse中,效果很好。但是,在Java 7中没有。在Java 7中似乎对类型推断有限制。在Java 1.8.0_05中工作。这为我编译…将代码复制/粘贴到Eclipse中,效果很好。但是,在Java 7中没有。在Java 7中似乎对类型推断有限制。在Java中工作1.8.0_05.但是
可调用
是一个接口,实现
可调用
的任何东西怎么可能不
可调用
?如果你说的是真的,那么当我将匿名类表达式提取到一个局部变量并将该局部变量传递给
s
时,它为什么要编译呢?@Dog我认为问题在于编译器的类型推断似乎指向可用的最特定类型(可调用的
子类),并且没有意识到通过遍历类型层次结构,它可以找到一个允许您编写的方法工作的类型。不过,Java 8的编译器足够聪明,因此不会发出错误。这也可能是匿名类处理方式中的一些错误。我不确定。@Dog Read。在Java 8中,类型推断得到了改进。在本例中,由于调用上下文,
s
中的
T
将被推断为
Callable
,一个
Callable
子类(匿名)将被接受为参数,并且该方法将被绑定为返回一个
列表
,该列表是
f
的有效参数。我知道这一点,但我不知道它在这里是如何应用的。@Dog表达式的类型
new Callable(){…}
实际上是
ASubTypeOfCallable
。与方法
s
一起使用,因此将
ASubTypeOfCallable
绑定到类型变量
T
。因此,该方法的返回类型为
List
,它不是
List
的子类型,因此不能用作
f
的参数。但是
Callable
是一个接口,实现
Callable
的任何东西怎么可能不是
Callable
?如果你说的是真的,那么当我将匿名类表达式提取到一个局部变量并将该局部变量传递到
s
时,它为什么要编译呢?@Dog我认为问题在于编译器的类型推断ce似乎将使用最具体的可用类型(可调用的
的子类),并且没有意识到通过遍历类型层次结构,它可以找到一个允许您编写的方法工作的类型。不过,Java 8的编译器足够聪明,因此不会发出错误。这也可能是匿名类处理方式中的一些错误。我不确定。@Dog Read。在Java 8中,类型推断得到了改进。在本例中,由于调用上下文,
s
中的
T
将被推断为
Callable
,一个
Callable
子类(匿名)将被接受为参数,并且该方法将被绑定为返回一个
列表
,该列表是
f
的有效参数。我知道这一点,但我不知道它在这里是如何应用的。@Dog表达式的类型
new Callable(){…}
实际上是
ASubTypeOfCallable
。与方法
s
一起使用,因此将
ASubTypeOfCallable
绑定到类型变量
T
。因此,该方法的返回类型为
List
,它不是
List
的子类型,因此不能用作
f
的参数。
static void f(List<? extends Callable<String>> l) {}