При приведении типов нет «только для чтения».Единственное, что вы делаете, это изменяете универсальный тип, то есть компилятор будет жаловаться на различияЕсли мы разберем код, у вас получатся два разных результата из-за интерпретации компилятором.
Первый:
List<?> list1 = list;
То, что вы сделали, - это "преуменьшение" a List<String>
доподстановочный знак List<?>
.Это означает, что что-либо вызовет ошибку компиляции просто потому, что он не может знать, каким должен быть / будет подстановочный знак.(вот почему добавление String привело к ошибке компиляции).
Во втором примере вы использовали «raw-type»:
List list2 = list;
Raw-type не заботитуниверсальные типы, как и компилятор в этом случае.Вот почему не было выброшено исключение, так как каждый типизированный параметр просто по умолчанию равен Object
(который является базовым классом каждого класса в Java).Следовательно, добавление целого числа (123
), которое также является объектом, вполне допустимо для компилятора.Однако во время выполнения выдается исключение, так как типы не совпадают.Именно по этой причине использование raw-типов считается плохой практикой, так как такие проблемы трудно найти / решить.