为什么谷歌集合或番石榴包含语义相等的函数?示例:
static
<T> Predicate<T>
and(Predicate<? super T>... components)
static
<T> Predicate<T>
and(Predicate<? super T> first, Predicate<? super T> second)
即所有可以接受几个参数的函数。
第二个问题是,为什么这些函数的定义使用泛型<? super T>
而不是<T>
?
要回答第一个问题,varargs版本(Predicate<? super T>...
)将在使用多个泛型谓词(例如Predicate<T>
)调用时向您发出关于未检查创建泛型数组的警告。对于组合两个谓词的常见情况,您不会得到警告。
为了回答第二个问题,取Predicate<? super T>
意味着在调用创建Predicate<Integer>
的方法时可以传入Predicate<Object>
(或Predicate<Number>
或其他)。例如,如果Predicates.notNull()
是Predicate<Object>
(应该是这样),并且您希望将其与某些Predicate<Integer>
组合在一起,那么如果参数的类型要求为Predicate<T>
,则这是不可能的。
我相信第一部分是为了性能。
在第二部分中,它必须是<? super T>
,因为Guava允许你放入任何谓词,这些谓词可以在T的任何超类型和T本身上求值。不仅仅是T本身,因为它只会有<T>
。这是有道理的,因为特定的谓词可能更通用,因此是在更通用的类型上定义的,但您希望将其与某些子类型一起使用。
树集构造函数TreeSet(Comparator<? super E> c)
也是如此。
另请参阅Generics教程第18页