你的理解是正确的。例如,一个接受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。