Общая путаница - PullRequest
       17

Общая путаница

1 голос
/ 19 мая 2009

Ниже приведен вопрос с подготовительного компакт-диска Kathy & Bert Bates SCJP 5. Я также опубликовал это в другом месте, но до сих пор не получил удовлетворительного объяснения ... Пожалуйста, помогите мне понять это:

public class BackLister {  
  //Insert code here
  {
    List<T> output=new LinkedList<T>();  
    for(T t:input)  
      output.add(0,t); 
    return output;  
  }  
}

Что из следующего может быть вставлено в //Insert code here?

  • A . public static <T> List<T> backwards(List<T> input)
  • B . public static <T> List<T> backwards(List<? extends T> input)
  • C . public static <T> List<T> backwards(List<? super T> input)
  • D . public static <T> List<? extends T> backwards(List<T> input)
  • E . public static <T> List<? super T> backwards(List<T> input)
  • F . public static <? extends T> List<T> backwards(List<T> input)

Я понимаю, что А и В верны; однако не почему D и E тоже правы. Я вижу, что C и F также неверны. Может кто-нибудь сказать мне, почему D и E являются правильными.

Ответы [ 2 ]

2 голосов
/ 19 мая 2009

Ответ D, public static <T> List <? extends T> backwards(List <T> input), возвращает список, который может содержать тип T или любой из его подклассов. Так как он может содержать T, он может содержать любой элемент на входе и является «правильным» в этом смысле.

Ответ E, public static <T> List <? super T> backwards(List <T> input), аналогичен, но возвращает список, который может содержать T или любой суперкласс. Поскольку он также может содержать элементы ввода, он также «правильный».

Выбор одной из этих альтернатив повлияет на то, что пользователь может ожидать от полученного списка.

  • С выходом List<? extends T> можно перебирать список и назначать каждому элементу переменную типа T, но ни один элемент, даже типа T, не может быть безопасно добавлен в List. (Кто-то может ссылаться на этот список как List<SubT> и получит ClassCastException при попытке получить T как SubT.)

  • С выходом List<? super T> можно безопасно добавлять элементы в List, если они имеют тип T. Однако элемент из списка можно безопасно назначить только переменной типа Object. (Кто-то может ссылаться на этот список как List<Object> и добавлять экземпляры Object или другие суперклассы T).

  • С помощью List<T> можно безопасно назначить элементы списка переменной типа T и добавить элементы типа T в список (при условии, что это модифицируемая List реализация).

1 голос
/ 19 мая 2009

Поскольку List<T> является List<? extends T> и List<? super T>, по определению.
? extends T - это подстановочный знак, указывающий T или подтип, а ? super T - это подстановочный знак, указывающий T или супертип. Следовательно, возвращение List<T> удовлетворит оба возвращаемых типа.

Есть причины предпочитать возвращать одно или другое, но главное здесь то, что они являются законными.

...