22

有什么区别:

static void findMax(LinkedList<? extends Number> list){...}

和:

static <T extends Number> void findMax(LinkedList<T> list){...}

由于两者都有效,我想知道两者之间是否有任何大的区别,建议使用哪个。

4

5 回答 5

14

主要区别在于,在第二个版本中您可以访问该类型T,而在第一个版本中您不能。

例如,您可能希望返回与 T 相关联的内容(例如返回 T 而不是 void):

static <T extends Number> T findMax(LinkedList<T> list){...}

或者您可能需要创建一个新的 T 列表:

static <T extends Number> void findMax(LinkedList<T> list){
    List<T> copyAsArrayList = new ArrayList<> (list);
    //do something with the copy
}

如果您不需要访问T,则两个版本在功能上是等效的。

于 2013-07-03T13:12:42.937 回答
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;
}

结论:

在功能上,它们几乎是等价的,只是无法修改具有未知类型 ( ) 的列表。?

于 2013-07-03T13:08:48.493 回答
4

这就是区别

static void findMax(LinkedList<? extends Number> list){
    list.add(list.get(0));  <-- compile error
}

您不能在列表中添加除 null 之外的任何内容。

同时编译时没有错误或警告

static <T extends Number> void findMax2(LinkedList<T> list){
    list.add(list.get(0));  <-- no error
}
于 2013-07-03T13:21:53.823 回答
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));
}
于 2013-07-07T05:06:13.160 回答
0

我认为关于第二种方法主体中参数 T 的访问已经有了很好的答案。

我想补充一点,如果您有许多需要按类型链接的参数,则需要第二种表示法。例子:

static <T extends Number> int getPosition(LinkedList<T> list, T element){...}

如果不使用泛型类型参数,您将无法强制执行上述约束<T>

于 2013-07-03T13:11:38.660 回答