这些方法定义有何不同?
public <T extends Foo> void loadData(Class<T> p_class);
public void loadData(Class<? extends Foo> p_class);
这两个签名接受完全相同的参数集,因此在这个意义上是等效的。正如评论中指出的那样,在第二种情况下,您将无法在方法体中引用T
。然而,根据Effective Java的说法,第二个签名更受欢迎(因为它更短且稍微更清晰)。在该书中,给出的建议是使用第二个签名,并在需要在方法中使用T
时使用具有第一个签名的私有帮助器方法。像这样:
private <T extends Foo> void helper(Class<T> p_class) {
// code
}
public void loadData(Class<? extends Foo> p_class) {
helper(p_class);
}
public <T, U, V extends Number> void foo(List<T> list, Map<U, V> map)
比public void foo(List<?> list, Map<?, ? extends Number> map)
更加复杂。在第二种情况下,List
可以是任何类型,Map
中的值必须是Number
的子类,这已经非常明显了。但在第一种情况下,有3个令人困惑的类型参数,你必须在两个地方看到extends Number
是关于映射值的。 - Paul BoddingtonT
的事实是调用者不关心的实现细节。调用者关心的只是如果他们传递一个扩展Foo
的某种类型的Class
对象,该方法是否有效。由于实现细节,他们不应该使用不同的签名。 - Paul Boddington在语法使用上有所不同,因为第二种方法具有通用类型参数。
class Bar extends Foo { }
obj.<Bar>loadData(klazz);
这需要 klazz 是确切的 Class<Bar>
。
T
。对于外部代码来说,一个方法能做到的另一个方法也能做到。 - newacct