我一遍又一遍地阅读tutorial,我只是不明白方法6的最后部分。
这个部分:
public static void printPersonsWithPredicate(
List<Person> roster, Predicate<Person> tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
因此,以下方法调用与在方法3中调用printPersons时相同:在本地类中指定搜索条件代码以获取有资格获得选择性服务的成员:
printPersonsWithPredicate(
roster,
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
因此,如果 p 是泛型类型,它怎么知道它是一个人?我只是不知道如何将自己区分为一个人,然后调用Person方法 - getGender()和getAge()。在这种情况下,p是否引用了周围类的类对象?
更新
根据提供的答案,这是正确的吗?
以下代码:
interface CheckPerson {
boolean test(Person p);
}
class CheckPersonEligibleForSelectiveService implements CheckPerson {
public boolean test(Person p) {
return p.gender == Person.Sex.MALE &&
p.getAge() >= 18 &&
p.getAge() <= 25;
}
}
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
printPersons(roster, new CheckPersonEligibleForSelectiveService());
与:
相同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
);
因为:
如果我错了,请告诉我,以便我能更新我的理解。我真的很想做到这一点。
答案 0 :(得分:1)
lambda表达式是Predicate<Person>#test
正文的定义,它将Person
作为参数。我们知道这是因为printPersonsWithPredicate
被声明为Predicate<Person>
,lambda作为参数被传递。
lambda的语法是->
的左侧是正在定义的方法的参数列表:
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
但是,编译器能够确定lambda的奇异参数p
必须是Person,因此可以省略它。因此缩短形式p -> ...
。
Approach #4中显示了与lambda相近的匿名类。
答案 1 :(得分:1)
一般情况下:参数只是从相关功能界面的类型签名推断,包括对通用参数的任何其他限制。
在这种情况下,我们知道第二个参数是Predicate<T>
。由于Predicate<T>
是方法test(T t)
的功能界面,因此我们知道p
的类型为T
(并且不是Predicate<T>
)。
由于T
的签名 Person
仅限于printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester)
,因此p
的实际类型为Person
RE:更新 - 答案是&#34;是&#34;和&#34;不&#34; :)
&#34;是&#34;,一般来说,类型推断的顺序可以用这种方式描述。
&#34;否&#34;,原因如下:
T
到Person
的类型。类型人只是&#34;共同点&#34;什么是允许的。例如:如果方法的签名包含:
Predicate<? extends JLabel>
- 然后参数类型实际上是JLabel
。Predicate<?>
- 然后参数类型实际上是Object
。Predicate<Person>
的类型是合法的,所以无需实际创建新的匿名类实现功能接口。实际上,在Java 8的当前JDK中,发生了什么。 Here's an article解释详情。答案 2 :(得分:0)
仅解决更新问题...
1)谓词接口已在java.util.function
中定义
正确
2)通过在方法参数中声明Predicate为Person:
不正确的。
您实际上已将tester
声明为Predicate<Person>
。你在这里根本没有声明Predicate
。 Predicate
是标准库声明的标准接口。
2a)我们隐式使用Person类型
实现谓词
正确......有点儿。您明确实施它。此处所需的lambda类型由printPersonsWithPredicate
的方法签名显式指定 ....具体来说,因为您声明形式参数tester
具有类型Predicate<Person>
。
2b)当使用泛型类型T(或缺少T)调用该方法时,该方法隐式推断该类型为Person
不是这种情况。