Подтвердить что ты не робот

Java Общий тип: разница между List <? extends Number> и List <T extends Number>

Java Общий тип: в чем разница между

(1) List <? extends Number>   
(2) List <T extends Number>

согласно моему пониманию

(1) List <? extends Number> - это Readonly Список "неизвестных" типов данных с суперклассом "Число". мы можем прочитать только элемент, но не можем добавить

(2) List <T extends Number> Список типов данных с суперклассом "Число". мы можем читать и добавлять элементы в список

См. пример ниже кода

class TestGen{

        public static void main(String[] args) {

        double result = 0.0;

        List<Integer> intList = new ArrayList<Integer>();
        intList.add(10);
        intList.add(20);
        intList.add(30);

        result = TestGen.sumOfList1(intList);
        System.out.println("Result=" + result); 

        result = TestGen.sumOfList2(intList);
        System.out.println("Result=" + result); 
    }

    public static double sumOfList1(List<? extends Number> list) {
        double s = 0.0;
        for (Number n : list)
            s += n.doubleValue();
        return s;
    }


    public static <T extends Number> double sumOfList2(List<T> list) {

        double s = 0.0;

        // -- --------------------------------------------------------- 
        // getting error while trying to add new element 
        // list<T> is not applicable for argument(Integer) : Why ?
        list.add(new Integer(40));                      

        for (Number n : list)               
            s += n.doubleValue();

        return s;
    }
}

Когда я пытаюсь добавить Integer (или даже объект Number) в sumOfList2, то получаю ошибку. Пожалуйста, объясните, что здесь не так?

4b9b3361

Ответ 1

Основное отличие заключается в том, что вы используете T extends Number, тогда вы можете обратиться к типу T
Например: list.add((T) new Integer(40));
Если вы используете ? extends Number, то вы не можете ссылаться на этот тип, но вы все равно можете сказать ((List<Integer>)list).add((int) s);

Ответ 2

В отдельности нет большой разницы. Однако два экземпляра List<? extends Number> в одном контексте полностью не связаны друг с другом, а два экземпляра List<T extends Number> в одном контексте относятся к одному и тому же T и тому же интерфейсу.

public void addAll(List<? extends Number> to, List<? extends Number> from) {
    for (Number n: from) {
        to.add(n);
    }
}

Этот метод терпит неудачу, потому что n не может быть добавлен в to, а также не удалось, поскольку типы членов from и to могут быть совершенно разными.

public <T> void addAll(List<T extends Number> to, List<T extends Number> from) {
    for (T n: from) {
        to.add(n);
    }
}

Этот метод отлично компилируется. Это не обязательно; Collections имеет лучшую версию, но будет работать без ошибок.

Ответ 3

В sumOfList2, T является конкретным подклассом Number, но он может быть любым из них. Например T может быть BigDecimal, и вы не можете добавить Integer в List<BigDecimal>.

Если вы хотите добавить любые числа в список, это должно быть List<Number>:

public static double sumOfList2(List<Number> list) {...}

Ответ 4

Первый случай очень прост и известен из T extends Number, что T - это объект, который относится к типу Number Number или его дочернему элементу. Это означает, что если у нас есть метод, который использует T как тип Number, мы можем манипулировать нашим методом соответственно i.e

<T extends Number> void myMethod ( List <T> num){
     num.add(1); // 1 is an Integer
     num.add(2.3) // 2.3 is a Double
} 

Но в этом * Диком характере '?' * Если мы не знаем, на какой объект будет ссылаться, даже если он расширяет число, но может быть любым объектом Object

void myMethod( List <? extends Number> num){
     // num.add(1); // not a valid statement, as we dont know if '1' is of the type '?'
     // num.add(2.3)  // not a valid statement, as we dont know if '2.3' is of the type '?'
}

Таким образом, единственное значение, которое может быть записано в таких выражениях, - null, поскольку любой тип объекта может быть нулевым.

    void myMethod( List <? extends Number> num){
      num.add(null)
    }

Такие методы являются методами только для чтения.