2

在 Core Java Volume I Edition 10 的泛型类型的第 8 章中,

注意:超类型边界的另一个常见用途是功能接口的参数类型。例如 Collection 接口有一个方法

default boolean removeIf(Predicate<? super E> filter)

该方法删除所有满足给定谓词的元素。例如,如果您讨厌具有奇怪哈希码的员工,您可以像这样删除它们:

ArrayList<Employee> staff = . . .; Predicate<Object> oddHashCode = obj -> obj.hashCode() %2 != 0; staff.removeIf(oddHashCode);

您希望能够通过 a Predicate<Object>,而不仅仅是 a Predicate<Employee>。超级通配符使这成为可能。

我在试图理解这一点时遇到了一些问题,这<? super E>意味着过滤器可以指向任何可以是超类EmployeeEmployee自身的谓词类型。

上面提到的文本我们可以传递一个Predicate<Object>to Predicate<? super E>

但是如果Predicate<? super E>指向Predicate<Employee>,可以Predicate<Object>传递到Predicate<Employee>吗?

我是不是误会了什么?

4

1 回答 1

2

你的理解是正确的。例如,一个接受Predicate<? super Employee>(如你的ArrayList<Employee>例子)的函数也可以接受一个Predicate<Object>like Objects::nonNull。从概念上讲,这是有道理的,原因如下:“我们(类)采用Predicate对我们或我们自己的任何(传递)超类进行操作的 a,因为我们与这些超类存在is-a关系。” 也就是说,一个接受anyObject并返回a的函数boolean等价地适用于,Employee因为Employee is-a Object,所以这个函数适用于Employee. 派生类与基类并不完全相同,但谓词(逻辑测试)仍然适用于派生类,因为将派生类作为基类来讨论是有意义的。

让我们来看一个例子:Employees可以从Person. 如果 Person可以用被Predicate<Person>调用来测试hasJob,那么在逻辑上也可以Employees测试hasJob。该函数Predicate<? super Employee>取而代之的Predicate<Employee>能力是维持该函数取逻辑上合理谓词的能力所必需的。另一方面,如果您只希望对Employees 进行某些属性测试,则可能只接受 a Predicate<Employee>,因为这对应于 onlyEmployee及其派生类具有对该属性进行测试的能力的逻辑可靠性。

要 100% 清楚这里发生了什么:

  • Predicate<? super Employee>接受s和Predicate任何超类,包括testEmployeeEmployee Object
  • Predicate<Employee>接受s和Predicate任何子类,不包括testEmployeeEmployee Object

给定这个类层次结构: SalariedEmployee is-a Employee is-a Person,会发生以下情况(P 是 的简写Predicate):

╔══════════════════╦═══════════╦═══════════════════╦═════════════╦═════════════════════╦═════════════════════╦═════════════════════════════╗
║       Type       ║ P<Person> ║ P<? super Person> ║ P<Employee> ║ P<? super Employee> ║ P<SalariedEmployee> ║ P<? super SalariedEmployee> ║
╠══════════════════╬═══════════╬═══════════════════╬═════════════╬═════════════════════╬═════════════════════╬═════════════════════════════╣
║ Person           ║ Accept    ║ Accept            ║ Reject      ║ Accept              ║ Reject              ║ Accept                      ║
║ Employee         ║ Accept    ║ Reject            ║ Accept      ║ Accept              ║ Reject              ║ Accept                      ║
║ SalariedEmployee ║ Accept    ║ Reject            ║ Accept      ║ Reject              ║ Accept              ║ Accept                      ║
║ Object           ║ Reject    ║ Accept            ║ Reject      ║ Accept              ║ Reject              ║ Accept                      ║
╚══════════════════╩═══════════╩═══════════════════╩═════════════╩═════════════════════╩═════════════════════╩═════════════════════════════╝

请注意,Accept/Reject表示可以输入 的类型,而Predicate不是 的实际结果Predicate

于 2019-10-03T14:06:31.620 回答