Разница между перечислением расширяет ZipEntry> и перечисление <ZipEntry>? - PullRequest
9 голосов
/ 06 марта 2009

Есть ли разница между перечислением <? расширяет ZipEntry> и перечисление ? Если так, то в чем разница?

Ответы [ 3 ]

16 голосов
/ 06 марта 2009

Нет практической разницы с точки зрения того, что вы можете сделать, когда у вас есть один из них, потому что параметр типа используется только в позиции «вывода». С другой стороны, есть большая разница в том, что вы можете использовать как один из них.

Предположим, у вас есть Enumeration<JarEntry> - вы не можете передать это методу, который взял Enumeration<ZipEntry> в качестве одного из аргументов. Вы могли бы передать его методу, принимающему Enumeration<? extends ZipEntry>.

Это более интересно, когда у вас есть тип, который использует параметр типа в позициях ввода и вывода - 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);
}

Для получения более подробной информации читайте:

4 голосов
/ 06 марта 2009

Да, прямо из одного из учебных пособий по обобщению солнца :

Здесь Shape - абстрактный класс с три подкласса: круг, прямоугольник, и треугольник.

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 голосов
/ 06 марта 2009

Теперь вы просто ушли и напомнили мне о чем-то, что я хотел бы иметь в мире C #.

Помимо предоставленных ссылок, в ответах на этот вопрос есть несколько хороших ссылок о C # и Java в отношении этой темы: Логика и ее применение к Collections.Generic и наследование

Выбор из которых:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...