Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

Особенности работы дженериков в Java

#java #ооп #generics


Прежде чем отвечать, прошу вдумчиво прочитать и осмыслить вопрос.
Итак у нас есть такой код, он скомпилируется и никаких ошибок не будет:

public static void main(String[] args) {
    method(4,"s");
}

static  void method(K k1, K k2) {

}


Я думал, что логически ошибка должна быть, ну раз нет, значит такие особенности джавы.
Далее, есть такой код:

public static void main(String[] args) {
    method(new ArrayList(), new Object());
}

static  void method(List k, K k2) {

}


Этот код уже выдает ошибку компиляции. Компилятор говорит, что я в method (List,
java.util.concurrent.Executor) засовываю не то, что надо. Действительно, Object это
вам не Executor. Но вот теперь главный мой вопрос почему в первом случае компилятору
пофиг, что одному и тому же параметризованному типу присваиваются разные типы данных,
а во втором случае компилятор на основе первого аргумента метода вычисляет какой должен
быть аргумент второго метода. Я не понимаю какая логика работает в обоих случаях.

И еще один не менее важный вопрос, если немного изменить второй пример кода вот так:

public static void main(String[] args) {
    method(new ArrayList(), 150);
}

static  void method(List k, K k2) {

}


Теперь никакой ошибки не возникает, причем мы можем пихать любые типы данных а компилятору
все равно! Мы всего лишь изменили List на List. Тут я уже даже теряюсь,
что это значит. Лист который содержит что-то, что наследует К, а что такое К? И почему
в итоге нам разрешено класть в параметры метода что угодно (напоминаю, что в предыдущем
примере с листом это не разрешено).
    


Ответы

Ответ 1



Границы для параметров параметризованных типов работают несколько иначе, нежели для простых типов. В первом случае оба типа могут быть приведены к Object, во втором случае тип может быть только либо Object, либо Executor. Если просто тип может быть легко "снижен" до объекта, то дженерики в параметризованных типах такое по умолчанию не позволяют - пока вы не укажете ? extends K, разрешающее использование наследников K, или ? super K, разрешающее использование предков K. В данном случае вы указали ? extends K, что позволяет использовать Object вместо K, таким образом список параметров метода формируется как List, Object. Могу быть в чем-то неправ, точные ответы на эти вопросы содержатся в JLS (Java Language Specification)

Комментариев нет:

Отправить комментарий