Общий метод Fail - PullRequest
       10

Общий метод Fail

1 голос
/ 18 февраля 2009

Я написал этот простой тестовый код, адаптировав фрагмент из книги, чтобы помочь мне понять работу универсальных методов в Java. Линия, которую я пометил: , предположительно работает, почему бы и нет?

import java.util.*;

class Test {
public static void main(String args[]){
    List<Number> input = null;
    List<Number> output=null;

    output = Test.process(input); // fail, why??

    } 
public static <E extends Number> List <? super E> process (List <E> nums){

    List <E>eList = new ArrayList<E>();
    return eList;
    }

}

edit: Ну, код работает при изменении List<? super E> на List<E>, это здорово, но я все еще не уверен, что я что-то упустил или книга, из которой я взял это, может иметь ошибку. Пожалуйста, прочитайте вопрос, как он появляется там:

  1. Учитывая метод, объявленный как:

публичный статический список <? super E> process (Список номеров)

Программист хочет использовать этот метод следующим образом:

// INSERT DECLARATIONS HERE
    output = process(input); 

Какие пары объявлений можно разместить в // ВСТАВИТЬ ДЕКЛАРАЦИИ ЗДЕСЬ, чтобы код для компиляции? (Выберите все подходящие варианты.)

A. ArrayList<Integer> input = null;
   ArrayList<Integer> output = null;

B. ArrayList<Integer> input = null;
   List<Integer> output = null;

C. ArrayList<Integer> input = null;
   List<Number> output = null;

D. List<Number> input = null;
   ArrayList<Integer> output = null;

E. List<Number> input = null;
   List<Number> output = null;

F. List<Integer> input = null;
   List<Integer> output = null;

G. None of the above.

Ответ: B, E и F верны. Возвращаемый тип процесса определенно объявлен как List, а не ArrayList, поэтому A и D не правы. C неверен, потому что тип возвращаемого значения оценивается как List<Integer>, и это не может присваиваться переменной типа List<Number>. Конечно, все это, вероятно, приведет к NullPointerException поскольку переменные по-прежнему равны нулю, но вопрос только задавался нам чтобы получить код для компиляции.

Ни одна из опций, упомянутых в книге, не сработала в моем коде. Могу ли я смело отметить это как ошибку со стороны Кэти Сьерры или я что-то здесь упускаю?

Ответы [ 3 ]

7 голосов
/ 18 февраля 2009

Проблема в том, что вы объявляете тип возврата вашего метода как

List<? super E>, i.e. List<? super Number>

, но присваивая его

List<Number>

Так что вы должны либо присвоить его

List<? super Number>

или объявить тип возврата как

List<E> i.e. List<Number>

(подробное форматирование, потому что встроенный код не показывает обобщенные значения правильно.)

Если в книге утверждается, что присваивать возвращаемое значение метода можно так, как вы его описываете, то в книге действительно есть ошибка. Было бы правильно, если бы метод возвращал список E (как указано выше).

1 голос
/ 18 февраля 2009

попробовать:

import java.util.*;

class Test {
public static void main(String args[]){
    List<Number> input = null;
    List<Number> output=null;

    output = Test.process(input); // fail, why??

    } 
public static <E extends Number> List <E> process (List <E> nums){

    List <E>eList = new ArrayList<E>();
    return eList;
    }

}
0 голосов
/ 18 февраля 2009

Ваш метод возвращает List. Мы не знаем, что это за список из , но это определенно список какого-то суперкласса из Number. Например: возможно, он возвращает список Object - звонящий не знает. Тем не менее, мы знаем, что какой бы тип List он не возвращал, всегда можно добавить Number.

Вы назначаете его на List of Number. Это означает, что всякий раз, когда вы звоните output.get(n), вы всегда получаете обратно Number.

Видите проблему? Возвращаемое значение process() не соответствует договору, которому output должен соответствовать.

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