之间有什么区别:
static void findMax(LinkedList<? extends Number> list){...}
和
static <T extends Number> void findMax(LinkedList<T> list){...}
既然两者都有效,我想知道两者之间是否存在重大差异,建议采用哪种方式。
答案 0 :(得分:14)
主要区别在于,在第二个版本中,您可以访问类型T
,而在第一个版本中,您不能访问。{/ p>
例如,您可能想要返回链接到T的内容(例如,返回T而不是void):
static <T extends Number> T findMax(LinkedList<T> list){...}
或者您可能需要创建一个新的Ts:
列表static <T extends Number> void findMax(LinkedList<T> list){
List<T> copyAsArrayList = new ArrayList<> (list);
//do something with the copy
}
如果您不需要访问T
,则两个版本在功能上都是等效的。
答案 1 :(得分:10)
findMax
接受符合特定条件的列表(在您的情况下是扩展Number
的类型列表),则应使用第一个。
static Number findMax(LinkedList<? extends Number> list) {
Number max = list.get(0);
for (Number number : list) {
if (number > max) {
max = number;
}
}
return max;
}
此方法返回Number
。例如,如果您有一个扩展Number
的类,并且您希望稍后在此方法的结果中使用某些特殊方法,则可能会出现问题。
T
,方法参数或方法的返回类型时,应使用第二个。
static <T extends Number> T findMax(LinkedList<T> list, T currentMax) {
T max = currentMax;
for (T number : list) {
if (number > max) {
max = number;
}
}
return max;
}
<强>结论:强>
从功能上讲,它们几乎等同于,除了, unknown 类型(?
)的列表无法修改。
答案 2 :(得分:4)
这是差异
static void findMax(LinkedList<? extends Number> list){
list.add(list.get(0)); <-- compile error
}
你不能在列表中添加任何空格。
同时编译时没有错误或警告
static <T extends Number> void findMax2(LinkedList<T> list){
list.add(list.get(0)); <-- no error
}
答案 3 :(得分:2)
就签名的权力而言,两者完全相同。我的意思是,如果您有任何使用第二个签名的API,您可以将其替换为使用第一个签名的API,并且使用该API的任何代码将完全像以前一样工作,以及任何之前无效的代码也行不通。所以对于外部代码,两者之间没有区别。
您如何将第二个的实施更改为第一个?其他人用list.add(list.get(0));
指出了例子。具有第一个签名的API是否可以执行该操作?是。这很简单。只需让第一个调用第二个(将第二个调用为内部私有方法)。这称为捕获助手。你可以这样做的事实证明,两者都可以从外部代码的角度“做”相同的事情(通过任何内部手段“做”,包括调用其他方法)。
static void findMax(LinkedList<? extends Number> list){
findMaxPrivate(list);
}
static static <T extends Number> void findMaxPrivate(LinkedList<T> list){
list.add(list.get(0));
}
答案 4 :(得分:0)
我认为在第二种方法体中访问参数T已经有了很好的答案。
我想补充一点,如果您有许多需要按类型链接的参数,则需要第二种表示法。例如:
static <T extends Number> int getPosition(LinkedList<T> list, T element){...}
如果不使用泛型类型参数<T>
,您将无法强制执行上述约束。