也许我没有完全理解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
}
}
答案 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);
中也未指定,并且是特定于实现的。