为什么lambda表达式无法解除引用?

kev*_*mes 1 java lambda dereference dot-operator java-8

import java.util.*;

class TreeMapDemo
{
    public static void main(String args[])
    {
        Comparator <String> c1 = (str1, str2) -> 0;

        Comparator <String> c2 = (str1, str2) -> 1;

        TreeMap <String, Double> tm1 = new TreeMap(c1.thenComparing(c2));
        //Working fine

        TreeMap <String, Double> tm2 = new TreeMap(((str1, str2) -> 0).thenComparing((str1, str2) -> 1));
        //Error: Lambda expression not expected here
        //<none> can not be dereferenced
    }
}
Run Code Online (Sandbox Code Playgroud)

我的查询是:

如果

c1 = (str1, str2) -> 0而且c2 = (str1, str2) -> 1,

那么为什么

c1.thenComparing(c2) 工作得很好

((str1, str2) -> 0).thenComparing((str1, str2) -> 1) 不是?

Joh*_*ger 7

Java依赖于lambda表达式的上下文来确定其类型.将lambda分配给变量或将其作为方法参数传递可提供足够的上下文,但thenComparing()在lambda上调用方法(如- )根本不提供有用的上下文.

这应该工作:

Comparator <String> c1 = (str1, str2) -> 0;
TreeMap <String, Double> tm2 = new TreeMap(c1.thenComparing((str1, str2) -> 1));
Run Code Online (Sandbox Code Playgroud)

更详细:

lambda表达式求值为实现某个函数接口的类型的对象,Java依赖于表达式出现的上下文来确定哪个函数接口.在第二种情况下,构造函数参数不是lambda的上下文; 调用thenComparing()是.它是该方法的返回值,它是构造函数参数.但是在Java可以确定任何事情之前,thenComparing()它需要知道调用它的对象的类型.类型通知方法,而不是相反.

Java无法从参数类型向后工作到所需的lambda类型,因为可能有任意数量的功能接口可以工作.Java不能假设所需的接口在标准库中.