В нескольких ответах на этот вопрос утверждается, что предупреждение связано с тем, что компилятор не может статически проверить , что приведение не может завершиться неудачей. Хотя компилятор действительно не может это проверить, это не повод для предупреждения! Если компилятор будет отмечать предупреждения для всех приведений, которые не могут быть проверены статически, это исключает все значимые приведения, потому что, когда приведение может быть проверено статически, вам обычно не нужно выполнять приведение в первую очередь. Другими словами, весь смысл операции приведения в том, что она может завершиться с ошибкой во время выполнения, что является идеальной ситуацией, которая обрабатывается с помощью ClassCastException
.
С другой стороны, предупреждение «unchecked cast» возникает, когда вы делаете приведение, для которого недостаточно информации о типе для проверки приведения во время выполнения . Это может произойти из-за стирания аргументов типа во время выполнения. Предположим, что вы применили что-то статического типа List<?>
к List<Vehicle>
. Во время выполнения объекты обоих этих типов просто имеют класс ArrayList
или LinkedList
в качестве единственной информации о типе времени выполнения без аргументов типа. Таким образом, компилятор не может вставить какой-либо код, который будет проверять во время выполнения, что объект действительно является List
из Vehicle
. Таким образом, компилятор ничего не делает, но выдает предупреждение «unchecked cast».
Это полезное предупреждение, потому что вы можете столкнуться с проблемой, когда начнете использовать результат приведения. Поскольку результат имеет статический тип List<Vehicle>
, вы можете написать код, который обрабатывает элементы из списка как Vehicle
, без необходимости писать приведение. Но на самом деле во время выполнения все еще происходит приведение, и оно завершится неудачей, когда окажется, что List
содержит все, что не является Vehicle
. Таким образом, вы можете получить ClassCastException
в точке, где вы этого не ожидали.
Безопасный способ обработать такое преобразование из List<?>
в List<Vehicle>
- это перебирать каждый из элементов, приводить их к Vehicle
(то, что вы можете проверить во время выполнения и которое поднимет ClassCastException
в четко определенную точку) и добавит их в новый список. Я написал некоторый общий код, чтобы сделать именно это в этом ответе .