关于java-8语法的简单问题。为什么JLS-8会限制这样的表达式:
Object of_ref = Stream::of; // compile-time error并且只允许这样的东西:
java.util.function.Function of_ref = Stream::of;
Object obj = of_ref; // compiles ok发布于 2015-03-16 16:55:47
这是因为方法引用或lambda表达式的目标类型应该是一个功能接口。仅基于此,运行时将创建一个提供给定功能接口实现的类的实例。将lambdas或方法引用视为abstract概念。将它分配给一个功能接口类型会给它一个具体的含义。
此外,特定的lambda或方法引用可以有多个功能接口作为其目标类型。例如,考虑以下lamda:
int x = 5;
FunctionalInterface func = (x) -> System.out.println(x);这是一个Consumer of x。此外,任何具有以下签名的抽象方法的接口:
public abstract void xxx(int value);可用作目标类型。那么,如果将lambda分配给Object类型,您希望运行时实现哪个接口?这就是为什么您必须显式地提供一个功能接口作为目标类型。
现在,一旦获得了包含实例的功能接口引用,就可以将其分配给任何超级引用(包括Object)。
发布于 2015-03-16 16:54:39
Object不是一个功能接口,方法引用只能分配给一个功能接口。参见例如JLS #15.13.2
如果T是函数接口类型(§9.8),则方法引用表达式在赋值上下文、调用上下文或转换上下文中与目标类型T兼容(§9.8),且表达式与从T派生的地面目标类型的函数类型一致。
发布于 2015-03-19 02:41:52
关键是Java中没有“函数类型”。lambda表达式本身没有"type“--它可以输入到唯一方法签名与lambda匹配的任何功能接口中。因此,lambda的类型基于其上下文提供的类型。您必须提供一个函数接口作为它获取类型的上下文。
考虑相同的问题(对于匿名类除外)是有指导意义的。尽管lambdas和匿名类之间存在实现上的差异,但在语义上,lambdas本质上等同于匿名类的子集,而lambda表达式始终可以转换为等效的匿名类创建表达式。
当你写:
Function<T, Stream<T>> of_ref = Stream::of;它相当于使用匿名类的以下内容:
Function<T, Stream<T>> of_ref = new Function<T, Stream<T>>() {
Stream<T> apply(T t) {
return Stream.of(t);
}
};现在考虑一下
Object of_ref = Stream::of;匿名类的等价物是什么?
Object of_ref = new [**What goes here?**]() {
[**What method signature goes here?**] {
return Stream.of(t);
}
};你知道为什么这没有意义--我们不知道用哪种类型作为匿名类的基类。
https://stackoverflow.com/questions/29082430
复制相似问题