java compiler, generics и наследование

142
10 декабря 2018, 23:30

Есть некий обобщенный интерфейс и класс, его реализующий.

interface Contract<T> {
    void doIt(T arg);
}
class Impl implements Contract<Integer> {
    @Override
    public void doIt(Integer arg) {
        System.out.println("hi");
    }
}

При создании экземпляра Impl и вызове метода следующим образом

Contract obj = new Impl();
obj.doIt(42);

компилятор вежливо предупреждает, что Unchecked call ... .

Я сделал следующий вывод - компилятор не смотрит на то, метод какого класса будет фактически вызван. Вот смотрит он что Contract#doIt(T arg) дергают и предупреждает, что надо бы тип передать. А то что тип передали в класс, который будет всю работу делать от него скрыто.

Я правильно всё понял?

Answer 1

Суть тут в том, что вы явно не указали, какой тип в дженерике будет, то есть компилятор не знает об этом, а это чревато ошибкой в рантайме. То есть в приведеном вами коде можно написать так:

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<Integer> obj = new Impl();

то передаваемый в этот bridge-метод параметр будет проверен на этапе компиляции и не даст вам выстрелить в ногу.

Рекомендую

READ ALSO
Изучение Spring (план / схема) [закрыт]

Изучение Spring (план / схема) [закрыт]

Задался вопросом изучения Spring, много информации, много видео, много книг, но нет ни одного плана / схемы, иллюстрации последовательности действий

168
Какие способы есть для подключения к серверу с помошью Android SDK

Какие способы есть для подключения к серверу с помошью Android SDK

Требуется подключиться к серверу и получить данные без помощи Retrofit или других библиотек, кроме непосредственно Android SDKAPI предоставляет для...

147
Наследование методов Java

Наследование методов Java

Есть класс Warship, в котором есть метод, ну например turnLeft()Я создаю класс Destroyer, который наследует от Warship, потом класс GroznyyKlass, который наследует...

145
Как избавиться от OnItemClickListener?

Как избавиться от OnItemClickListener?

Есть код для выбора пункта меню для удаления позиции с ArrayList:

133