我正在学习Java Generics。我的理解是Generics按类型参数化集合。在Oracle教程中,有以下注释:
在通用代码中,问号(?),称为通配符, 代表一种未知的类型。
在下一页上,下面是参数中带有上限通配符的方法声明示例:
public void process(List<? extends Foo> list)
鉴于此,我想知道为什么这种方法声明是非法的:
public void process(List<E extends Number> list)
虽然这是合法的:
public <E extends Number> void process(List<E> list)
答案 0 :(得分:5)
指定方法parm类型时,您使用的是泛型类型,因此必须事先定义它。在本声明中,您使用的是没有定义的E
public void process(List<E extends Number> list) { /* ... */ }
但是,在第二个中,它是在方法返回类型(void)之前定义的:
public <E extends Number> void process(List<E> list) { /* ... */ }
答案 1 :(得分:3)
没有比“因为语言的设计方式更好”的答案。但是考虑它的一种方法是类型参数被视为方法的另一个参数列表:它们必须一次出现在一个(有序)列表中。
您可以通过显式传递类型参数来调用泛型方法:例如,foo.<Integer, String>process(list)
。这意味着类型参数必须具有明确的顺序,就像普通的值参数一样。
答案 2 :(得分:2)
完成@ phoenix的回答,这句话中的问题
public void process(List<E extends Number> list) { /* ... */ }
是你的通用类型E的声明是在错误的地方。正确的位置在返回类型之前:
public <E extends Number> void process(List<E> list) { /* ... */ }
但是,另一个定义泛型类型的可能位置是类声明本身:
class MyClass<E extends Number> {
public void process(List<E> list) { /* ... */ }
}
答案 3 :(得分:0)
大约两者都相同,但我只使用第一个。