#java #generics
#java #обобщения
Вопрос:
public class Demo {
public static void main(String[] args) {
ArrayList<Integer> list = getList();
System.out.println(list.toString());
list.add(1);
System.out.println(list.toString());
}
public static <T> ArrayList<T> getList(){
ArrayList<String> strings = new ArrayList<>();
strings.add("qwert");
return (ArrayList<T>) strings;
}
}
Как показано в приведенном выше коде, почему разрешено присваивать ArrayList
JDK11 выводит
[qwert]
1
Комментарии:
1. Я бы порекомендовал вам прочитать Generics на Java .
2. Использование
(casting)
похоже на сообщение компилятору «поверь мне, я знаю, что я делаю». Когда существует какой -то безопасный сценарий для приведения, компилятор не будет жаловаться, и все, что после этого, будет ошибкой программистов.3. Кастинг здесь плохой. Проблема в том, что приведение сообщает компилятору «Я знаю лучше вас, поэтому рассматривайте это как массив целых чисел, даже если это не так»
4. Я получаю предупреждение о непроверенном приведении от компилятора Java при компиляции этого кода. Итак, компилятор все-таки предупреждает.
Ответ №1:
Почему
ArrayList<T>
может присваиватьсяArrayList<Integer>
Это потому, что вы предоставили явное приведение типов.
Вероятно, вы не в состоянии понять, как ArrayList<Integer> list
можно удерживать qwert
. Опять же, это потому, что вы попросили компилятор доверять вам, что вы вкладываете Integer
в него.
В конце концов, вся информация о типе удаляется, когда дело доходит до времени выполнения. Вам нужно понять концепцию удаления типа.
Ответ №2:
return (ArrayList<T>) strings;
Здесь строка ArrayList напрямую не преобразуется в Integer ArrayList, вместо этого она преобразуется в T ArrayList. В соответствии с «выводом целевого типа» в документах:
static <T> List<T> emptyList();
List<String> listOne = Collections.emptyList();
Этот оператор ожидает экземпляр List; этот тип данных является целевым типом. Поскольку метод emptyList возвращает значение типа List, компилятор делает вывод, что аргумент типа T должен быть строкой значения.