Lambda 作为 Predicate 接口中方法的组合,如果它被写成一条语句则无法编译

Lambda as a combination of methods from the Predicate interface doesn't compile if it is written as one statement

这两种创建 lambda 的方式有什么区别?为什么第一个不编译?

Predicate<Integer> predicate = Predicate.isEqual(0).or(Predicate.isEqual(1));

给出: 错误:类型不兼容:Predicate<Object> 无法转换为 Predicate<Integer> = Predicate.isEqual(0).or(Predicate.isEqual(1));

Predicate<Integer> pred21 = Predicate.isEqual(0);
Predicate<Integer> pred22 = pred21.or(Predicate.isEqual(1));

这个有效。

isEqual 方法调用之前添加 <Integer> 应该会有所帮助:

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0).or(Predicate.isEqual(1));

这种编译器行为背后的原因:

  • isEqual 是一个静态泛型方法,它 returns Predicate<T> (不管它的输入参数的实际类型是什么),所以它 returns Predicate<Object> 在调用方法时未明确指定返回类型。
  • or 也是一个静态泛型方法,但是它 returns 一个谓词参数化了相同的类型,作为它的输入参数(即 Predicate<Object>)。

发生这种情况是因为

Predicate.isEqual(0)

有这个签名:

static <T> Predicate<T> isEqual(Object targetRef)

如果您不输入它,它会推断 Predicate<Object>

要键入它,您可以键入 return 类型

Predicate<Integer> pred21 = Predicate.isEqual(0);

或像这样输入电话

Preicate.<Integer>isEqual

看签名:

 static <T> Predicate<T>    isEqual​(Object targetRef)

在第一个例子中,编译器无法猜测泛型类型参数,所以它returns一个Predicate<Object>

在一行中键入它的正确方法是指定类型参数,例如

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0).or(Predicate.isEqual(1));

问题与推理在 Java 中的工作方式有关:它取决于目标。

这里:

Predicate<Integer> predicate = Predicate.isEqual(0)
                                        .or(Predicate.isEqual(1));

or(Predicate.isEqual(1)) 编辑的 return 类型取决于 Predicate.isEqual(0) 编辑的 return 类型(最近的目标),但此调用未指定任何其他类型作为 return.
所以 Object 是由 or(Predicate.isEqual(1)) 编辑的,因为方法 isEqual()T 定义为没有任何通配符的 return 类型:

static <T> Predicate<T> isEqual(Object targetRef) {

要解决您的问题,您确实需要指定第一次调用的 return 类型,以便链式调用能够推断出正确的类型:Integer.

Predicate<Integer> predicate = Predicate.<Integer>isEqual(0)
                                        .or(Predicate.isEqual(1));