简体   繁体   English

枚举之间的区别<!--? extends ZipEntry-->和枚举<zipentry> ?</zipentry>

[英]Difference between Enumeration<? extends ZipEntry> and Enumeration<ZipEntry>?

Is there a difference between Enumeration<?枚举<? extends ZipEntry> and Enumeration<ZipEntry>?扩展 ZipEntry> 和 Enumeration<ZipEntry>? If so, what is the difference?如果是这样,有什么区别?

There's no practical difference in terms of what you can do when you've got one of them, because the type parameter is only used in an "output" position.当您拥有其中一个时,您可以做什么并没有实际区别,因为类型参数仅用于“输出”position。 On the other hand, there's a big difference in terms of what you can use as one of them.另一方面,在您可以用作其中之一方面存在很大差异。

Suppose you had an Enumeration<JarEntry> - you couldn't pass this to a method which took Enumeration<ZipEntry> as one of its arguments.假设您有一个Enumeration<JarEntry> - 您不能将它传递给将Enumeration<ZipEntry>作为其 arguments 之一的方法。 You could pass it to a method taking Enumeration<? extends ZipEntry>可以将其传递给采用Enumeration<? extends ZipEntry> Enumeration<? extends ZipEntry> though.虽然Enumeration<? extends ZipEntry>

It's more interesting when you've got a type which uses the type parameter in both input and output positions - List<T> being the most obvious example.当你有一个在输入和 output 位置都使用类型参数的类型时更有趣 - List<T>是最明显的例子。 Here are three examples of methods with variations on a parameter.以下是三个参数变化的方法示例。 In each case we'll try to get an item from the list, and add another one.在每种情况下,我们都会尝试从列表中获取一个项目,然后添加另一个。

// 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);
}

For more details, read:有关更多详细信息,请阅读:

Yes, straight from one of the sun generics tutorials :是的,直接来自太阳 generics 教程之一:

Here Shape is an abstract class with three subclasses: Circle, Rectangle, and Triangle.这里的 Shape 是一个抽象的 class 具有三个子类:圆形、矩形和三角形。

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

It is worth noting that the draw() method can only be called on lists of Shape and cannot be called on a list of Circle, Rectangle, and Triangle for example.值得注意的是,draw() 方法只能在 Shape 列表上调用,而不能在例如 Circle、Rectangle 和 Triangle 列表上调用。 In order to have the method accept any kind of shape, it should be written as follows:为了让该方法接受任何类型的形状,它应该写成如下:

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

Now you've just gone and reminded me of something I wish we had over in the C# world.现在你刚刚离开并让我想起了我希望我们在 C# 世界中结束的事情。

Other than the links provided, there's some good links about C# and Java in relation to this topic in the answers to this question: Logic and its application to Collections.Generic and inheritance Other than the links provided, there's some good links about C# and Java in relation to this topic in the answers to this question: Logic and its application to Collections.Generic and inheritance

A selection of which are:其中的一个选择是:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM