Есть некий обобщенный интерфейс и класс, его реализующий.
interface Contract
class Impl implements Contract
@Override
public void doIt(Integer arg) {
System.out.println("hi");
}
}
При создании экземпляра Impl и вызове метода следующим образом
Contract obj = new Impl();
obj.doIt(42);
компилятор вежливо предупреждает, что Unchecked call ... .
Я сделал следующий вывод - компилятор не смотрит на то, метод какого класса будет фактически вызван. Вот смотрит он что Contract#doIt(T arg) дергают и предупреждает, что надо бы тип передать. А то что тип передали в класс, который будет всю работу делать от него скрыто.
Я правильно всё понял?
Ответ
Суть тут в том, что вы явно не указали, какой тип в дженерике будет, то есть компилятор не знает об этом, а это чревато ошибкой в рантайме. То есть в приведеном вами коде можно написать так:
Contract obj = new Impl();
obj.doIt("123"); //можно передать String и компилятор это съест
Но когда вы запустите этот код, вы получите ClassCastException. Почему?
Потому что в случае с дженериком в параметре метода компилятор создает так называемый bridge-метод и после компиляции ваш класс Impl будет иметь 2 метода:
public void doIt(Integer arg) {
System.out.println("hi");
}
public void doIt(Object arg) {
doIt((Integer) arg); //тут ClassCastException
}
компилятор вежливо предупреждает, что Unchecked call
Собственно, предупреждает, потому что если вы напишите вот так:
Contract
то передаваемый в этот bridge-метод параметр будет проверен на этапе компиляции и не даст вам выстрелить в ногу.
Рекомендую
Комментариев нет:
Отправить комментарий