上限有限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
超类型,尽管Foo
是Bar
超类型。 但是,第一种方法通过,因为类型参数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"
对于问题中的示例,类型变量仅使用一次,因此它等同于使用超类。 在这种情况下,你应该避免声明一个类型变量,它只是不必要的混乱。
另外我应该注意,另一个答案改变了使用List
和List
的例子,但是如评论中所提到的,超类真的是List extends Foo>
List extends Foo>
,因此也不需要类型变量。