Lambda Java 8 currying函数,无法确定int[]返回类型

Lambda Java 8 currying函数,无法确定int[]返回类型,lambda,types,java-8,currying,java-10,Lambda,Types,Java 8,Currying,Java 10,假设我们有这样一个lambda函数: Function<ArrayList<Integer>, int[]> func1 = a->new int[2]; Function<Object, Function<Object, int[]>> func2 = a->b->new int[2]; Function<ArrayList<Integer>, Function<Object, int[]>&g

假设我们有这样一个lambda函数:

Function<ArrayList<Integer>, int[]> func1 = a->new int[2];
Function<Object, Function<Object, int[]>> func2 = a->b->new int[2];
Function<ArrayList<Integer>, Function<Object, int[]>> func3 = a->b->new int[2];


现在让我们假设我们有一个像这样的currying lambda函数:

Function<ArrayList<Integer>, int[]> func1 = a->new int[2];
Function<Object, Function<Object, int[]>> func2 = a->b->new int[2];
Function<ArrayList<Integer>, Function<Object, int[]>> func3 = a->b->new int[2];


现在是第三种变化,这就是我的困惑所在,也是我的问题所在。假设我们有一个像这样的currying lambda函数:

Function<ArrayList<Integer>, int[]> func1 = a->new int[2];
Function<Object, Function<Object, int[]>> func2 = a->b->new int[2];
Function<ArrayList<Integer>, Function<Object, int[]>> func3 = a->b->new int[2];
错误是:

Main.java:23:错误:不兼容的类型:无法将对象转换为int[]
int[]func3Result3=func3.apply(新ArrayList()).apply(null);//没有
^

为什么它认为返回类型是
对象
而不是
int[]
?内部函数的返回类型明确说明返回类型为
int[]
。如果两个lambda的参数都是
Object
func2
test),或者集合中附加了菱形(
func3Result1
func3Result2
),则它可以正常工作。但由于某种原因,当从集合中删除菱形时(
func3Result3
),它会变得混乱,即使
int[]
返回类型与此
ArrayList
输入无关


编辑:刚刚在我的jdk版本1.8.0_72上对它进行了本地测试,在那里它可以编译和工作。有人能确认它在JDK1.9或1.10(或JDK1.8的最新版本之一)上确实不起作用吗?也许问题在于TIO在这里做了一些奇怪的事情,而不是JDK本身简而言之。当您使用原始类型(如@Holger在注释中提到的)时,您会删除任何通用信息。所以这句话:

int[] func3Result3 = func3.apply(new ArrayList()).apply(null);
可分为多行进行澄清:

Function temp = func3.apply(new ArrayList());
这里,只返回
函数
,因为使用原始类型
new ArrayList()
会删除泛型信息

原始类型的函数有些类似,但不等于
函数

这使得现在很容易看到,当将
null
应用于该函数时,您不知道返回的是什么(除了它是
对象
),这就是为什么会出现该错误:

int[] func3Result3 = temp.apply(null);
由于类型擦除,编译器不知道类型

这其中的寓意是:

不要使用原始类型。它们只是一种向后兼容特性,不应该在现代生产代码中使用


@霍尔格:谢谢你的阅读。我确实知道你永远不应该使用它,尽管现在我也更好地理解了它背后的原因。我仍然有点困惑Java是如何以某种方式将
ArrayList
输入类型与当前lambda中的
int[]
返回类型联系起来的,尽管它们之间应该没有任何关系。我很好奇是否有人能为这些特殊情况提供编译器中发生的实际JVM代码。在Java 8之前,您可以简单地说,使用原始类型导致表达式根本不使用泛型,因此它可能无法从完全不相关的类型变量推断类型。众所周知的例子,
List…String[]数组=list.toArray(新字符串[0])列表
,即使
toArray
的类型参数与
列表
的类型参数无关,code>也无法工作。从Java8及其扩展的目标类型推断开始,规则变得更加复杂,编译器之间的差异(bug、修复bug、规范清理)也就不足为奇了。从Java9到更高版本,他们严格了泛型参数的推断,这可能就是为什么Ynice回答+1!至于主要部分:“在这里,只返回
函数
,因为使用原始类型
new ArrayList()
”会擦除泛型信息。我仍然有点不明白为什么。为什么当输入是
new ArrayList()
(或
new ArrayList()
)时返回
Function
,而当输入是原始类型的
new ArrayList
时只返回
Function
?当一个原始类型的输入被用于一个强类型的对象(
Function
,在本例中)时,输出也总是成为原始类型的,这是正确的吗?@KevinCruijssen这正是正在发生的事情。一旦使用了原始类型。使用该原始类型的所有其他对象也将丢失类型信息。这在包含其他泛型类型对象的泛型类中最为明显。例如,
类框{List strings;List getStrings(){return strings}}
如果没有为
指定泛型类型参数,那么
getStrings()
将只返回一个
列表
,尽管它似乎没有受到影响。现在仍然是