你的理解是正确的。例如,一个接受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>
能力是维持该函数取逻辑上合理谓词的能力所必需的。另一方面,如果您只希望对Employee
s 进行某些属性测试,则可能只接受 a Predicate<Employee>
,因为这对应于 onlyEmployee
及其派生类具有对该属性进行测试的能力的逻辑可靠性。
要 100% 清楚这里发生了什么:
Predicate<? super Employee>
接受s和Predicate
的任何超类,包括test
Employee
Employee
Object
Predicate<Employee>
接受s和Predicate
的任何子类,不包括test
Employee
Employee
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
。