在官方Java教程中阐明Lambda表达式的工作原理

在官方Java教程中阐明Lambda表达式的工作原理,java,Java,我读了一遍又一遍,只是不理解方法6的最后一部分 具体而言,本部分: public static void printPersonsWithPredicate( List<Person> roster, Predicate<Person> tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } }

我读了一遍又一遍,只是不理解方法6的最后一部分

具体而言,本部分:

public static void printPersonsWithPredicate(
    List<Person> roster, Predicate<Person> tester) {
    for (Person p : roster) {
        if (tester.test(p)) {
            p.printPerson();
        }
    }
}
公共静态void printPersonsWithPredicate(
列表(列表、谓词测试仪){
人员(p:名册){
if(测试仪测试(p)){
p、 printPerson();
}
}
}
因此,以下方法调用与在方法3中调用PrintPerson时相同:在本地类中指定搜索条件代码以获取符合选择性服务条件的成员:

printPersonsWithPredicate(
    roster,
    p -> p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25
);
printPersonsWithPredicate(
名册
p->p.getGender()==Person.Sex.MALE
&&p.getAge()>=18

&&p.getAge()lambda表达式是的主体的定义,它将
Person
作为参数。我们之所以知道这一点,是因为
printPersonsWithPredicate
声明为使用
谓词,lambda将作为参数传递给该谓词

lambda的语法是
->
的左侧是所定义方法的参数列表:

(Person p) -> p.getGender() == Person.Sex.MALE
    && p.getAge() >= 18
    && p.getAge() <= 25
(Person p)->p.getGender()==Person.Sex.MALE
&&p.getAge()>=18
&&p.getAge()…


类似于lambda的匿名类如所示。

一般来说:该参数仅根据相关函数接口的类型签名推断,包括对泛型参数的任何附加限制

在本例中,我们知道第二个参数是
谓词
。由于
谓词
是与方法的函数接口,我们知道
p
的类型是
T
(而不是
谓词

由于
T
通过
printPersonsWithPredicate(列表花名册,谓词测试员)
的签名限制为
Person
,因此
p
的实际类型为
Person


RE:UPDATE-答案是“是”和“否”:

“是”,一般来说,类型推断的顺序可以这样描述

“否”,理由如下:

  • 在2.2中,我认为最好声明该方法将
    T
    的类型限制为
    Person
    。类型“人”只是允许的“公分母”。例如:如果方法的签名将包含:
    • 谓词
      -那么参数类型实际上就是
      对象
  • 最好说明编译器推断出的有关类型的内容,而不是由编译器以外的其他东西“隐式定义”的内容。您可能会认为这是一个吹毛求疵的问题,但这种转变有两个重要的后果:
    • 它可以将你从“不是X不等于N,而是Y”的推理陷阱中拯救出来
    • 非常具体地说,由于编译器能够推断一种类型的
      谓词
      是合法的,因此无需实际创建实现函数接口的新匿名类。事实上,在Java8当前的JDK中,就是这样发生的。解释细节

仅解决更新问题

1) 谓词接口已在java.util.function中定义

正确的

2) 通过在方法参数中将谓词声明为Person:

不对

实际上,您将
tester
声明为
谓词
。这里根本没有声明
谓词<代码>谓词
是标准库声明的标准接口

2a)我们用一种类型的Person隐式实现谓词

对。。。某种程度上。您正在显式地实现它。这里需要的lambda类型是明确指定的。。。通过
printPersonsWithPredicate
的方法签名。特别是,因为您将形式参数
tester
声明为具有类型
谓词

2b)当使用泛型类型T(或缺少泛型类型T)调用该方法时,该类型由该方法隐式推断为Person


在这种情况下不行。

谢谢,这对我来说很有意义。然而,我还是有点困惑。根据你的回答,我更新了我的问题,以澄清我的理解。请让我知道我是否正确。@user3804927:我看到有人已经添加了关于更新的答案,但以防万一,我已经编辑了一个“洁净室”回复。谢谢,这对我来说是有意义的。然而,我还是有点困惑。根据你的回答,我更新了我的问题,以澄清我的理解。请让我知道我是否做对了我发现这段视频在30分钟时对“类型推断”有一个很好的解释,下面的一个答案没有给出。谢谢你,我真正困惑的部分是类型推断,这在上一篇文章中已经解释过,并在YouTube视频中进一步澄清。在处理布尔运算时,JDK 8引入了谓词的概念,并且通过类型推断(在Java中也是一个新概念),编译器能够确定p的类型。
import java.util.function // import the Predicate<T> interface

public static void printPersonsWithPredicate(
    List<Person> roster, Predicate<Person> tester) {
    for (Person p : roster) {
        if (tester.test(p)) {
            p.printPerson();
        }
    }
}

printPersonsWithPredicate(
    roster,
    p -> p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25
);
(Person p) -> p.getGender() == Person.Sex.MALE
    && p.getAge() >= 18
    && p.getAge() <= 25