我了解集合的获取和放置原理:如果某个方法接受一个集合,它将向其中写入类型T,则参数必须为Collection<? super T>
;而如果它将从中读取类型T,则参数必须为Collection<? extends T>
。
但是有人可以解释一下Collections.max()
签名:
public static <T> T max(Collection<? extends T> coll,
Comparator<? super T> comp)
特别是为什么Comparator<? super T>
而不是Comparator<? extends T>
?
Josh Bloch的助记符 PECS 在这里很有用。它代表:
生产者extends
,消费者super
这意味着,当一个参数化的类型被传递给的方法将 产生 的实例T
(它们将从它以某种方式被检索),? extends T
应该被使用,因为子类的任意实例T
也是T
。
当将参数化类型传递给方法时,将 使用的 实例T
(它们将被传递给该方法以执行某些操作),? super T
因为应将的实例T
合法地传递给接受某些超类型的任何方法T
。例如,Comparator<Number>
可以在上使用Collection<Integer>
。? extends T
将无法正常工作,因为Comparator<Integer>
不能对进行操作Collection<Number>
。
编辑: 要澄清更多关于获取/放置(生产/消费):
public T something();
^
以上是产生的方法T
。
public void something(T t);
^
上面是消耗的方法T
。
“生产者extends
,消费者super
”适用于如何将参数化对象传递给该对象的方法。对于Collections.max()
,将从中检索项目Collection
,因此它是生产者。这些项目将作为参数传递给on上的方法Comparator
,因此它是使用者。
问题内容: 我以为我明白了这一点,但显然不是…… 我有这样的方法签名: 但是如果我尝试打电话 我收到一个编译错误:“类型中的方法doSomething(List)…不适用于参数(List>)” 但是,如果我更改为 它仍然不起作用,但是 显然,它可以绕开泛型使用。 这似乎很奇怪。 有人可以填写我吗? 另外,在这种情况下,我想使用任何包含任何通用类型的TypeAs的List;undefined,Typ
我正在尝试制作一些适用于数字的通用函数,但我正在努力处理函数签名。 也许我是从错误的角度来讨论这个问题,但到目前为止,我是在这里独立完成的。我并不是一心要这样做;因此,如果我从错误的角度来解决这个问题(创建一个通常有用的数学函数库),那么一定要教育我。 假设我想要一个函数,将两个数字相加: 这不会编译。这里是一个游乐场:https://play.integer32.com/?version=sta
我有一个方法,我想在其中接受必须扩展抽象类的类类型。之间的区别是什么 ? 在第二种情况下,我不能直接引用方法内部的类型。哪些类类型可以传递给这两个方法有什么不同吗?
问题内容: 我想用泛型和varargs实现一个函数。 这里的意图是断言传递给该函数的所有参数都是扩展作为第一个参数给出的Class的Class对象。因此main方法的前两行将进行编译,而第三行将生成错误。 我的问题是: 为什么前两行会显示“类型安全性:为varargs参数创建了Class的通用数组”消息? 我在这里想念什么吗? 附加问题: 如何重新设计它以防止在调用“ doNastyThingsT
问题内容: 我有一个代表文本片段的泛型类。该文本片段可能具有多种不同模式(突出显示的不同类型)中的任何一种。这些模式用枚举表示。每个项目的Enum可能不同,但是它必须实现一个接口,该接口提供了一种将其中两个结合的方法(可以突出显示并加粗显示)。所以我有一个界面: 然后我的TextFragment是文本字符串和模式的容器。但是当我尝试声明该类时: 我收到以下错误: 令牌“扩展”的语法错误,预期 根据