在 lambda 表达式中使用默认方法

Chr*_*kov 4 java lambda java-8 default-method

根据JLS 15.27.2,lambda 主体与周围上下文具有相同的范围,我想知道是否有特定原因来说明为什么 lambda 实现的接口中的默认方法在主体中也不可用? 此限制是否启用了一些优化,还是只是为了保持重载规则简单?

我今天正在对一些 Java 8 API 进行原型设计,当我遇到这个限制时,我感到非常失望,因为使用默认方法可以让我以一种非常优雅和非侵入性的方式实现该 API。

通过要求静态导入或多或少可以实现相同的优雅,但这会导致“污染”命名空间。

有没有可能取消这个限制?

Han*_*k D 5

默认方法对 lambda 不可用,因为在将 lambda 分配给函数类型之前,它尚未被赋予类型。例如,拉姆达

s -> s.isEmpty()
Run Code Online (Sandbox Code Playgroud)

可以分配给 ajava.util.function.Predicate或 a com.google.common.base.Predicate。出于这个原因,它无法访问java.util.function.Predicate的默认方法,直到它java.util.function.Predicate通过直接赋值给 a java.util.function.Predicate,通过将 lambda 作为java.util.function.Predicate参数传递,从返回类型为 的函数返回它java.util.function.Predicate,或者简单地将其强制转换为一个java.util.function.Predicate是这样的:

((Predicate<String>) s -> s.isEmpty()).negate();   // negate is a default method on Predicate
Run Code Online (Sandbox Code Playgroud)

考虑它的一种方式类似于装箱一个int值。 Integer的方法不能在文字整数值上调用,但是一旦将整数值分配给一种Integer类型,就可以调用它的方法。

  • 我明白你的意思,我不打算为编译器设计辩护。我的理解,FWIW,是一个 lambda 是一个没有签名的主体,一个函数接口是一个没有主体的签名,直到赋值或强制转换,这两者才被连接起来并生成一个实际的函数。希望有帮助。 (2认同)