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

330
17 июня 2017, 12:24

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

public static void main(String[] args) {
    method(4,"s");
}
static <K> void method(K k1, K k2) {
}

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

public static void main(String[] args) {
    method(new ArrayList<Executor>(), new Object());
}
static <K> void method(List<K> k, K k2) {
}

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

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

public static void main(String[] args) {
    method(new ArrayList<Executor>(), 150);
}
static <K> void method(List<? extends K> k, K k2) {
}

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

Answer 1

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

Могу быть в чем-то неправ, точные ответы на эти вопросы содержатся в JLS (Java Language Specification)

READ ALSO
java альтернатива JxBrowser и javafx WebView

java альтернатива JxBrowser и javafx WebView

Собственно есть ли бесплатная ли альтернатива JxBrowser ?

286
Как сделать прогресс-бар для показа буферизации в онлайн аудио плеере

Как сделать прогресс-бар для показа буферизации в онлайн аудио плеере

Класс, в котором происходит выбор трека (url-канала) для проигрывания:

365
Проблема с подключением файла БД при сборке в Maven

Проблема с подключением файла БД при сборке в Maven

Доброго времени суток, собираю свой проект с помощью Maven и возникла проблема с получением файла БД как ресурсаСоздаю соединение таким вот...

371