Java 8 BiPredicate 在第一个参数上自动调用方法?

Java 8 BiPredicate automatically calling method on first argument?

我有以下代码:

public class BiPredicateTest {
    public static void main(String[] args) {
        BiPredicate<List<Integer>, Integer> listContains = List::contains;
        List aList = Arrays.asList(10, 20, 30);
        System.out.println(listContains.test(aList, 20));       // prints true magically?
    }
}

在语句 listContains.test(aList, 20) 中,如何在第一个参数上调用方法 "contains" 并将第二个参数作为参数传入?相当于:

System.out.println(aList.contains(20));

换句话说,语句 listContains.test(aList, 20) 如何转换为 aList.contains(20)?

java 8 BiPredicate 是这样工作的吗?有人能解释一下魔法是如何发生的吗(有一些参考资料)?

这不是重复的 post。这与 "What does “an Arbitrary Object of a Particular Type” mean in java 8?" 的不同之处在于它没有明确传递方法引用。很清楚如何在您引用的 post 中传递方法引用。调用该方法的数组实例作为参数传递给 Arrays.sort()。在我的例子中,如何在 aList 上调用方法 "contains" 并不明显。我正在寻找有关其工作原理的参考或解释。

似乎有些人更喜欢投反对票而不是提供参考或解释。他们给人的印象是他们有知识但拒绝分享。

BiPredicate 是一个只有一个方法的接口,test

public interface BiPredicate<A,B> {
    boolean test(A a, B b);
}

只有一种方法的接口称为功能接口。在 Java 8 之前,您经常必须使用匿名 class 来实现这些接口,只是为了为具有相同签名的特定方法调用创建包装器。像这样:

BiPredicate<List<Integer>,Integer> listContains = new BiPredicate<>() {
    @Override
    public boolean test(List<Integer> list, Integer num) {
        return list.contains(num);
    }
};

在 Java8 中,添加了方法引用,这使得此模式的语法更短,字节码更高效。在方法引用中,您可以指定一个方法或构造函数,它与接口的类型参数具有相同的签名。当您使用 class 类型进行方法引用时,它会将 class 类型指定为正在使用的功能接口的第一个通用参数。这意味着使用该通用类型的任何参数都需要是 class.

的实例

即使实例方法通常不带任何参数,仍然可以使用以实例为参数的方法引用。例如:

Predicate<String> pred = String::isEmpty;
pred.test(""); // true

有关详细信息,请参阅 Java Tutorial for Method References