括号内的Java泛型方法参数类型。外括号

时间:2013-07-03 13:07:05

标签: java generics

之间有什么区别:

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

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

既然两者都有效,我想知道两者之间是否存在重大差异,建议采用哪种方式。

5 个答案:

答案 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>,您将无法强制执行上述约束。