Ошибка помещения объектов суперкласса в нижний ограниченный список подстановочных знаков - PullRequest
0 голосов
/ 14 июня 2019

Я понимаю, что использование подстановочного знака с нижним ограничением в списке в качестве параметра метода должно позволить поместить элементы этой нижней границы и ее супертипы, но рассмотрим следующий код:

public class WildcardError {
    void foo(List<? super Number> i) {
        i = new ArrayList<Integer>(); //compile error
        i.add(new Integer(2)); // no error
    }
}

Теперь я понимаю, почемуявляется ошибкой компиляции в первом утверждении метода foo, так как ArrayList из Integer не является подтипом списка «? super Number», но тогда почему мы можем поместить Integer в этот список, даже если целое число не является супертипом Number?И наоборот, в следующем коде:

public class WildcardError {
    void foo(List<? super Integer> i) {
        i = new ArrayList<Number>(); //no error
        Number k =20;
        i.add(k); // compile error
    }
}

Здесь я понимаю, что в операторе 2 не должно быть ошибки компиляции, поскольку ArrayList of Number является подтипом списка «? Super Integer», но почемутам ошибка компиляции в последнем утверждении?

Хотя?super Integer должен содержать номер суперкласса.

Я пытался найти ответ, но не могу найти точный сценарий.

1 Ответ

1 голос
/ 14 июня 2019

В первом примере нижняя граница ? super Number означает, что фактический параметр типа может быть либо Number, либо супертипом (например, Object). Поскольку дженерики Java являются инвариантами, List<? super Number> не может соответствовать ArrayList<Integer>. Помните, что нижняя граница связана с параметром типа, а не с типом аргументов, которые могут быть отправлены в качестве аргумента. Нет ошибки при вызове add, потому что Integer может быть передано методу add, который может принимать Number или суперкласс.

Во втором примере нижняя граница ? super Integer означает, что фактический параметр типа может быть либо Integer, либо супертипом (например, Number, Object). Это соответствует ArrayList<Number>, поэтому здесь нет ошибок. Тем не менее, тип i по-прежнему List<? super Integer>, что не гарантирует возможность принимать Number, например k. В любое время это может означать List<Integer>, где Number, который может быть Double, не следует принимать. Вот почему здесь ошибка компилятора.

...