为什么此Java 8方法参考不适用于System.out.println(LocalDate :: now);?

时间:2019-05-25 06:42:10

标签: java java-8

也许我没有完全理解Java 8功能接口和/或方法引用的概念。我只是不明白为什么以下代码具有“此表达式的目标类型必须是功能接口”:

import java.time.LocalDate;

interface Today{
    LocalDate getTodayDate(); 
}

要测试的课程:

class Test{
    public static void main(String[] args) {

        Today today = () -> LocalDate.now();
        System.out.println(today::getTodayDate);//Problem with this one                 
    }   
}

2 个答案:

答案 0 :(得分:3)

您在目标类型未知的上下文中使用方法引用。

如果java.io.PrintStream使用类似以下的方法,那将奏效:

public void println(Today dateSupplier){
    print(dateSupplier.getTodayDate());
}

但这不是println的签名。

没有理由这样做,但是使代码工作的方法是调用您自己的接口方法,但这是没有道理的...

System.out.println(today.getTodayDate()); //calls println(Object)

除非该合同涉及多个类/类型,否则您可能需要重新设计代码。

答案 1 :(得分:2)

在问题描述中,您说得到的错误是:“此表达式的目标类型必须是功能接口”;但是显示的行:

System.out.println(today::getTodayDate);//Problem with this one

将显示不同的错误消息。因此,我认为需要更广泛的解释。

看来您首先需要创建一个名为@FunctionInterface的{​​{1}}才能使此代码正常工作,例如:

Today

创建后,它也将起作用:

@FunctionalInterface
interface Today {
    LocalDate getTodayDate();
}

相当于:

Today today = () -> LocalDate.now(); 

创建Today today = LocalDate::now; 并没有真正的必要,因为Today存在并且执行相同的操作-不输入任何内容并返回java.util.Supplier<T>;但是如果您想玩转-可以。

实际上,您已经引入了此T界面这一事实将使解释变得容易一些。

编译器看到:Today(在today::getTodayDate行中),必须“理解”这是什么;至少可能是 两件事:System.out.println(today::getTodayDate); Today-无法确定;这就是为什么说lambda表达式和方法引用是 poly表达式的原因-它们的类型是在使用情况下推断出来的(就像泛型一样)。由于编译器无法分辨出真正的含义,因此它将失败。

您可以对该类型进行显式转换,以便编译:

java.util.Supplier

或:

System.out.println((Today) today::getTodayDate);

但是问题是,即使此程序可以编译,运行并打印“内容”,其实际打印的内容在System.out.println((Supplier<LocalDate>) today::getTodayDate); 中也未指定,并且是特定于实现的。