上限有限泛型VS超类作为方法参数?

时间:2014-01-27 20:12:24

标签: java generics

据我所知,使用上限有限泛型并使用超类作为方法参数都接受相同的可能参数。哪个是首选,两者之间有什么区别?如果有的话?

上限有限泛型作为参数:

public <T extends Foo> void doSomething(T foo) {}

超类作为参数:

public void doSomething(Foo foo) {}

2 个答案:

答案 0 :(得分:6)

这是一个上限类型参数。使用super创建下限,您无法真正为类型参数执行此操作。 You can't have a lower bounded type parameter

如果您想要传递List<T>,那将会产生影响。因此,对于以下两种方法:

public <T extends Foo> void doSomething(List<T> foos) {}
public void doSomething(List<Foo> foo) {}

对于给定的班级:

class Bar extends Foo { }

以下方法调用:

List<Bar> list = new ArrayList<Bar>();
doSomething(list);

对第一种方法有效,但对第二种方法无效。第二种方法失败,因为List<Foo>不是List<Bar>的超类型,尽管Foo是超级类型的Bar。但是,第一种方法通过,因为类型参数T将被推断为Bar

答案 1 :(得分:1)

通常,只有在类/方法/字段声明中的多个位置使用时才需要类型变量。当你在方法(而不是类)上声明一个时,唯一使用它的地方是参数和该方法的返回值。

例如,您可以在多个参数上使用它以确保其类型匹配:

public static <T> void addToList(List<T> list, T element) {
    list.add(element);
}

这是一个简单的例子,但你可以看到它阻止你给它一个与列表的通用类型不匹配的元素:

List<Integer> list = new ArrayList<>();
addToList(list, 7);
//addToList(list, 0.7); // doesn't compile
//addToList(list, "a"); // doesn't compile

您还可以将参数和返回类型声明为相同的类型:

public static <T> T nullCheck(T value, T defValue) {
    return value != null ? value : defValue;
}

由于此方法返回了它给出的两个T对象中的一个,我们可以放心地说返回的对象也是T类型。

Integer iN = null;
Integer i = nullCheck(iN, 7);
System.out.println(i); // "7"

Double dN = null;
Double d = nullCheck(dN, 0.7);
System.out.println(d); // "0.7"

Number n = nullCheck(i, d); // T = superclass of Integer and Double
System.out.println(n); // "7"

对于问题中的示例,类型变量仅使用一次,因此它等同于使用超类。在这种情况下,你应该避免声明一个类型变量,它只是不必要的混乱。

另外我应该注意,另一个答案更改了使用List<T>List<Foo>的示例,但正如评论中所提到的,超类实际上是List<? extends Foo>,所以没有类型变量是也需要那里。