Ответ 1
Да, это безопасно. Общая проверка выполняется только во время компиляции.
Если у вас есть необработанный тип на Java, вы можете смело назначить/применить его к тому же типу с неограниченным подстановочным знаком. Например, List
можно безопасно отнести к List<?>
, который удаляет его необработанную природу и позволяет использовать его в безопасном (с типом) способом 1.
С другой стороны, Java не позволяет выставлять из самого List
с параметром raw, например List<Optional>
, в список одного и того же типа с неограниченным шаблоном, например List<Optional<?>>
.
Вы все еще можете сделать это, сбросив весь исходный List
и снова выполнить резервное копирование (неявно через назначение):
List<Optional> rawOptionalList = null;
List<Optional<?>> wildcardOptionalList = (List)rawOptionalList;
Конечно, это вызывает предупреждение о непроверенном преобразовании (от List
до List<Optional<?>>
).
Мне кажется, что это преобразование гарантировано безопасно: не List<Optional<?>>
так же безопасно, как List<Optional>
таким же образом, что безопасное литиевание Optional
в Optional<?>
?
1... но вы никогда не сможете добавить что-либо в этот список, поскольку ничто не будет соответствовать захвату ?
для метода add(?)
. Это цена, которую вы платите за безопасность.
Да, это безопасно. Общая проверка выполняется только во время компиляции.
Тип erasure в Java означает, что все параметризованные типы стираются во время выполнения. В вашем случае a List<Optional>
- это всего лишь List
во время выполнения, а Optional<MyClass>
- это всего лишь Optional
во время выполнения.
Когда вы получаете содержащийся класс из List
или Optional
, Java делает приведение к параметризованному типу. Таким образом, ваш код не только безопасен, это именно то, что делает компилятор Java.