Непроверенное приведение, в отличие от проверенного, не проверяет безопасность типов во время выполнения.
Вот пример, основанный на разделе Consider typesafe heterogenous containers
3-го издания. «Эффективная Java» Джошуа Блоха, но класс контейнера намеренно нарушен - он хранит и возвращает неправильный тип:
public class Test {
private static class BrokenGenericContainer{
private final Map<Class<?>, Object> map= new HashMap<>();
public <T> void store(Class<T> key, T value){
map.put(key, "broken!"); // should've been [value] here instead of "broken!"
}
public <T> T retrieve(Class<T> key){
// return key.cast(map.get(key)); // a checked cast
return (T)map.get(key); // an unchecked cast
}
}
public static void main(String[] args) {
BrokenGenericContainer c= new BrokenGenericContainer();
c.store(Integer.class, 42);
List<Integer> ints = new ArrayList<>();
ints.add(c.retrieve(Integer.class));
Integer i = ints.get(0);
}
}
Если retrieve()
использует непроверенное приведение - (T)map.get(key)
- запуск этой программы приведет к ClassCastException
в строке Integer i = ints.get(0)
. Метод retrieve()
завершится, потому что фактический тип не был проверен во время выполнения:
Exception in thread "main"
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at Test.main(Test.java:27)
Но если retrieve()
использует проверенный актерский состав -
key.cast(map.get(key))
- запуск этой программы приведет к появлению ClassCastException
в строке key.cast(map.get(key))
, поскольку проверенный приведение обнаружит, что тип неправильный, и выдаст исключение. Метод retrieve()
не будет завершен:
Exception in thread "main" java.lang.ClassCastException:
Cannot cast java.lang.String to java.lang.Integer
at java.lang.Class.cast(Class.java:3369)
at Test$BrokenGenericContainer.retrieve(Test.java:16)
at Test.main(Test.java:26)
Может показаться небольшой разницей, но в случае с непроверенным броском String
успешно превратился в List<Integer>
. В реальных приложениях последствия этого могут быть ... ну, серьезными. В случае с проверенным приведением, несоответствие типов было обнаружено как можно раньше.
Чтобы избежать предупреждения о непроверенных приведениях, можно использовать @SuppressWarnings("unchecked")
, если программист действительно уверен, что метод действительно безопасен. Лучшая альтернатива - использовать дженерики и проверенные приведения, когда это возможно.
Как сказал Джошуа Блох,
... непроверенные предупреждения важны. Не игнорируйте их.
Ради полноты этот ответ касается специфики Eclipse.