我试图在一定深度上理解下界通配符的用法。我正在尝试编写一个通用方法copy
,它将一个List
的内容复制到另一个<T> void copy(List<T> dest, List<? extends T> src)
。我想出了这个方法签名:
<T> void copy(List<? super T> dest, List<? extends T> src)
我认为这个签名可以全面解决所有情况。但是,我在Java Collections类中看到方法签名是这样的:
List<? super T> dest
我不明白为什么他们使用List<T> dest
而不是clientsAllocation[j] = input.privateFIFOName;
。他们的签名是否有一些额外的灵活性?
答案 0 :(得分:5)
没有明确的证人类型,没有实际区别。
如果没有指定Eran所做的类型见证,两种方法之间的灵活性没有差异。
基本上,使用? super T
而不是T
只是一种风格差异,但这是更好的做法,可以通过应用一些好的代码原则来看出:
? super T
更明确地显示dest
应采用的类型。src
上的类型约束来了解dest
可以采用的类型。extends
而消费者参数(下面的“out”)应该使用super
关键字。 Java tutorials也建议使用? super T
(他们甚至使用copy
函数):
出于本讨论的目的,将变量视为提供两个函数之一是有帮助的:
“In”变量
“in”变量向代码提供数据。想象一下copy
方法有两个参数:copy(src, dest)
。src
参数提供要复制的数据,因此它是“in”参数。“退出”变量
“out”变量保存数据以供其他地方使用。在copy
示例copy(src, dest)
中,dest
参数接受数据,因此它是“out”参数。在决定是否使用通配符以及适合使用哪种类型的通配符时,可以使用“in”和“out”原则。以下列表提供了遵循的准则:
通配符指南:
- “in”变量使用上限有限的通配符定义
extends
关键字。- “out”变量定义为下限 通配符,使用
super
关键字。
答案 1 :(得分:1)
以下是一个例子:
以下代码段使用签名<T> void copy(List<? super T> dest, List<? extends T> src)
传递编译,但不能使用签名<T> void copy(List<T> dest, List<? extends T> src)
:
YourClass obj = new YourClass ();
List<HashMap<String,String>> lhm = new ArrayList<>();
List<Map<String,String>> lm = new ArrayList<>();
obj.<HashMap<String,String>>copy (lm,lhm);