要传递给 <?超级 T> 在 Java
Types of argument to be passed to <? super T> in Java
核心泛型类型第 8 章 Java 第一卷第 10 版,
NOTE: Another common use for supertype bounds is an argument type of a
functional interface. For example, the Collection interface has a method
default boolean removeIf(Predicate<? super E> filter)
The method removes all elements that fulfill the given predicate. For example,
if you hate employees with odd hash codes, you can remove them like this:
ArrayList<Employee> staff = . . .;
Predicate<Object> oddHashCode = obj -> obj.hashCode() %2 != 0;
staff.removeIf(oddHashCode);
You want to be able to pass a Predicate<Object>
, not just a Predicate<Employee>
. The
super wildcard makes that possible.
我在试图理解这一点时遇到了一些问题,所以 <? super E>
意味着过滤器可以指向可以是 Employee
或 Employee
本身的超类的任何谓词类型。
上面的文字提到我们可以将Predicate<Object>
传递给Predicate<? super E>
。
但是如果Predicate<? super E>
指向Predicate<Employee>
,Predicate<Object>
可以传递给Predicate<Employee>
吗?
我是不是误会了什么?
您的理解是正确的。例如,采用 Predicate<? super Employee>
的函数(如您的 ArrayList<Employee>
示例)也可以接受 Predicate<Object>
,例如 Objects::nonNull
。从概念上讲,这是有道理的,原因如下: "We (the class) take a Predicate
that operates on us, or on any of the (transitive) superclasses of ourself, because we have an is-a relationship with those superclasses." 也就是说,一个函数取任何 Object
和 returns 一个 boolean
等价地适用于 Employee
因为Employee
是-a Object
,所以把这个函数应用到Employee
上是有效的。派生class与基class并不完全相同,但谓词(逻辑测试)仍然适用于派生class,因为谈论派生[=是有意义的81=] 作为基础 class。
让我们来看一个例子:Employees
可以派生自 Person
。如果
Person
可以用名为 hasJob
的 Predicate<Person>
进行测试,那么在逻辑上也可以为 hasJob
测试 Employees
。该函数采用 Predicate<? super Employee>
而不仅仅是 Predicate<Employee>
的能力是维持函数采用逻辑上合理的谓词的能力所必需的。另一方面,如果您只期望 Employee
会针对某些 属性 进行测试,您可能只接受 Predicate<Employee>
,因为这对应于仅 [=] 的逻辑合理性18=] 及其派生的 classes 具有针对 属性.
进行测试的能力
要 100% 清楚这里发生的事情:
Predicate<? super Employee>
接受 Predicate
那个 test
s Employee
和 [=18 的任何超级 class =], 包括 Object
Predicate<Employee>
接受 Predicate
test
的 Employee
和 [=18 的任何子 class =],其中 排除 Object
给定此 class 层次结构:SalariedEmployee is-a Employee is-a Person
,这是发生的情况(Predicate
的 P 是 shorthand):
╔══════════════════╦═══════════╦═══════════════════╦═════════════╦═════════════════════╦═════════════════════╦═════════════════════════════╗
║ 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
的实际结果。
核心泛型类型第 8 章 Java 第一卷第 10 版,
NOTE: Another common use for supertype bounds is an argument type of a functional interface. For example, the Collection interface has a method
default boolean removeIf(Predicate<? super E> filter)
The method removes all elements that fulfill the given predicate. For example, if you hate employees with odd hash codes, you can remove them like this:
ArrayList<Employee> staff = . . .; Predicate<Object> oddHashCode = obj -> obj.hashCode() %2 != 0; staff.removeIf(oddHashCode);
You want to be able to pass a
Predicate<Object>
, not just aPredicate<Employee>
. The super wildcard makes that possible.
我在试图理解这一点时遇到了一些问题,所以 <? super E>
意味着过滤器可以指向可以是 Employee
或 Employee
本身的超类的任何谓词类型。
上面的文字提到我们可以将Predicate<Object>
传递给Predicate<? super E>
。
但是如果Predicate<? super E>
指向Predicate<Employee>
,Predicate<Object>
可以传递给Predicate<Employee>
吗?
我是不是误会了什么?
您的理解是正确的。例如,采用 Predicate<? super Employee>
的函数(如您的 ArrayList<Employee>
示例)也可以接受 Predicate<Object>
,例如 Objects::nonNull
。从概念上讲,这是有道理的,原因如下: "We (the class) take a Predicate
that operates on us, or on any of the (transitive) superclasses of ourself, because we have an is-a relationship with those superclasses." 也就是说,一个函数取任何 Object
和 returns 一个 boolean
等价地适用于 Employee
因为Employee
是-a Object
,所以把这个函数应用到Employee
上是有效的。派生class与基class并不完全相同,但谓词(逻辑测试)仍然适用于派生class,因为谈论派生[=是有意义的81=] 作为基础 class。
让我们来看一个例子:Employees
可以派生自 Person
。如果
Person
可以用名为 hasJob
的 Predicate<Person>
进行测试,那么在逻辑上也可以为 hasJob
测试 Employees
。该函数采用 Predicate<? super Employee>
而不仅仅是 Predicate<Employee>
的能力是维持函数采用逻辑上合理的谓词的能力所必需的。另一方面,如果您只期望 Employee
会针对某些 属性 进行测试,您可能只接受 Predicate<Employee>
,因为这对应于仅 [=] 的逻辑合理性18=] 及其派生的 classes 具有针对 属性.
要 100% 清楚这里发生的事情:
Predicate<? super Employee>
接受Predicate
那个test
sEmployee
和 [=18 的任何超级 class =], 包括Object
Predicate<Employee>
接受Predicate
test
的Employee
和 [=18 的任何子 class =],其中 排除Object
给定此 class 层次结构:SalariedEmployee is-a Employee is-a Person
,这是发生的情况(Predicate
的 P 是 shorthand):
╔══════════════════╦═══════════╦═══════════════════╦═════════════╦═════════════════════╦═════════════════════╦═════════════════════════════╗
║ 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
的实际结果。