2009-03-06 67 views

回答

16

因为类型参数仅用于“输出”位置,所以当您获得其中一个时,您可以执行的操作没有实际区别。另一方面,你可以使用作为其中之一。

假设你有一个Enumeration<JarEntry> - 你不能把它传递给一个以Enumeration<ZipEntry>为参数的方法。你可能把它传递给一个采取Enumeration<? extends ZipEntry>虽然。

当你有一个在输入和输出位置都使用type参数的类型时更有趣 - List<T>是最明显的例子。以下是三个参数变化的方法示例。在每种情况下,我们都会尝试从列表中获取一个项目,然后再添加一个项目。

// Very strict - only a genuine List<T> will do 
public void Foo(List<T> list) 
{ 
    T element = list.get(0); // Valid 
    list.add(element); // Valid 
} 

// Lax in one way: allows any List that's a List of a type 
// derived from T. 
public void Foo(List<? extends T> list) 
{ 
    T element = list.get(0); // Valid 
    // Invalid - this could be a list of a different type. 
    // We don't want to add an Object to a List<String> 
    list.add(element); 
} 

// Lax in the other way: allows any List that's a List of a type 
// upwards in T's inheritance hierarchy 
public void Foo(List<? super T> list) 
{ 
    // Invalid - we could be asking a List<Object> for a String. 
    T element = list.get(0); 
    // Valid (assuming we get the element from somewhere) 
    // the list must accept a new element of type T 
    list.add(element); 
} 

欲了解更多详情,请阅读:

+0

一个ZipEntrySubclass像JarEntry(ZipFile.entries使用通配符的原因)? – 2009-03-06 11:35:21

+0

谢谢汤姆 - 将编辑我的答案:) – 2009-03-06 11:56:55

4

是,直接从sun generics tutorials之一:

这里Shape是一个抽象类 三个子类:Circle,Rectangle, 和Triangle。

public void draw(List<Shape> shape) { 
    for(Shape s: shape) { 
    s.draw(this); 
    } 
} 

值得注意的是,平局() 方法只能在 形状的列表来调用,不能在列表上叫做圆形,矩形,三角形和对 例如 。为了让方法 接受任何类型的形状,它应该是 写成如下:

public void draw(List<? extends Shape> shape) { 
    // rest of the code is the same 
} 
0

现在你刚刚走了,提醒我的东西,我希望我们在C#全球已经有超过。

除了链接提供的,有关于C#和Java中关系在回答这个问题的一些好的链接到这个话题:Logic and its application to Collections.Generic and inheritance

的选择,其中包括: