上限有限genericsVS超类作为方法参数?

据我所知,使用上限有限generics并使用超类作为方法参数都接受相同的可能参数。 哪个更受欢迎,两者之间有什么区别?

上限有限generics作为参数:

public  void doSomething(T foo) {} 

超类作为参数:

 public void doSomething(Foo foo) {} 

这是一个上限的类型参数。 使用super创建下限,您无法真正为类型参数创建。 您不能拥有较低的有界类型参数 。

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

 public  void doSomething(List foos) {} public void doSomething(List foo) {} 

对于给定的类:

 class Bar extends Foo { } 

以下方法调用:

 List list = new ArrayList(); doSomething(list); 

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

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

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

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

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

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

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

 public static  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" 

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

另外我应该注意,另一个答案改变了使用ListList的例子,但是如评论中所提到的,超类真的是List List ,因此也不需要类型变量。