В ссылках на методы конструктора разница между использованием параметров универсального типа и нет?

Я читаю «Эффективную Java 3» и заметил этот код в статье 43: «Предпочитайте ссылки на методы вместо лямбда-выражений»:

TreeMap<K,V>::new

Обратите внимание на параметры типа. Я всегда просто делал:

TreeMap::new

Я использую Intellij и никогда не получал предупреждений об этом или каких-либо рекомендаций по его изменению. На самом деле, когда IDE изменяет указанную выше ссылку на метод на лямбду, она преобразует ее в

() -> new TreeMap<Integer, Integer>()

Какова ценность включения параметров типа? Разве компилятор не может вывести это на основе параметров типа переменной? Судя по тому, как среда IDE преобразовала ссылку на метод в лямбда-выражение, кажется, что это возможно.


person Ivan    schedule 09.03.2018    source источник
comment
Обычно может. В тех случаях, когда это невозможно, вот как вы это делаете.   -  person Louis Wasserman    schedule 09.03.2018
comment
Обычно об этом можно догадаться, но в прошлом я считал это необходимым.   -  person shmosel    schedule 09.03.2018


Ответы (1)


Ссылка на конструктор TreeMap::new аналогична использованию вывода типа ромба (§15.13.1):

Для удобства, когда имя универсального типа используется для ссылки на метод экземпляра (где приемник становится первым параметром), целевой тип используется для определения аргументов типа. Это облегчает использование, например, Pair::first вместо Pair<String,Integer>::first.

Точно так же ссылка на метод, такая как Pair::new, обрабатывается как создание экземпляра алмаза (new Pair<>()). Поскольку ромб является неявным, эта форма не создает необработанный тип; на самом деле нет способа выразить ссылку на конструктор необработанного типа.

Вам нужно будет указать аргументы типа явно в более или менее тех же ситуациях, что и когда вам нужно будет явно предоставить аргументы типа конструктору.

Например, в дальнейшем вызов get предотвращает рассмотрение присваивания возврата во время вывода supplier, поэтому T выводится как ArrayList<Object>:

class Example {
    public static void main(String[] args) {
        ArrayList<String> list =
            supplier(ArrayList::new).get(); // compile error
    }
    static <T> Supplier<T> supplier(Supplier<T> s) { return s; }
}

В этом надуманном примере нам пришлось бы использовать ArrayList<String>::new.

person Radiodef    schedule 09.03.2018