ссылка на метод в Java 8? - PullRequest
1 голос
/ 14 марта 2019

Я читал в уроках, что при использовании ссылки на метод аргументы должны совпадать в методе и методе функционального интерфейса, на которые мы ссылаемся. Итак, я получаю следующую ошибку.

public class MethodRefTest 
{
    public static void m1(int i)
    {
        System.out.println("Hey in method 1");
    }


    public static void main(String[] args)
    {

        Runnable r=MethodRefTest::m1; //Compile time error

    }
}

Теперь, когда я понял, почему я получаю эту ошибку Посмотрите на приведенный ниже фрагмент кода

package com;

public class Transaction {

    private int id;
    private int value;

    public Transaction(int id,int value)
    {
        this.id=id;
        this.value=value;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }


}


package com;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class MethodRefTest {

    public static void main(String[] args)
    {

        Transaction t1=new Transaction(1,20);
        Transaction t2=new Transaction(2,30);
        List<Transaction> list=new ArrayList<Transaction>();
        list.add(t1);
        list.add(t2);
        List<Integer> intList=list.stream().map(Transaction::getId).collect(Collectors.toList());
        System.out.println(intList);

    }
}

В методе map, который я использовал, он принимает Function FunctionalInterface ... но ссылка на метод, которую я использовал, не имеет аргументов, но у метода apply (T t) Function есть один аргумент, и getId () не имеет аргументов, в этом случае он не выдает никакой ошибки, даже если аргументы не совпадают.

Пожалуйста, помогите мне понять это?

Ответы [ 3 ]

0 голосов
/ 14 марта 2019

Ссылка на метод

Transaction::getId

равно лямбда-выражению

(Transaction t) -> t.getId()

То, что вы видите, принимает аргумент Transaction и возвращает int значение

Это абсолютно действительная подпись Function<Transaction, Integer>, поскольку она полностью выполняет свои требования.

0 голосов
/ 14 марта 2019

Компилятору Java разрешено сопоставлять ссылку на метод с не-1001 * методом с n - 1 аргументами, как если бы он совпадал, с самим объектом в качестве первого аргумента. Соответствующий раздел JLS - 15.13.1 :

В противном случае, учитывая целевой тип функции с типами параметров P 1 , ..., P n и набор потенциально применимых методов, объявление времени компиляции выбирается как следующим образом:

  • Если выражение ссылки на метод имеет вид ReferenceType :: [TypeArguments] Идентификатор , то выполняется два поиска наиболее конкретного применимого метода. Каждый поиск такой, как указано в §15.12.2.2–15.12.2.5, с пояснениями ниже. Каждый поиск производит набор применимых методов и, возможно, обозначает наиболее конкретный метод из набора. В случае ошибки, указанной в §15.12.2.4, набор применимых методов пуст. В случае ошибки, указанной в §15.12.2.5, не существует наиболее конкретного метода.

    В первом поиске ссылка на метод обрабатывается так, как если бы это был вызов с выражениями аргументов типов P 1 , ..., P n . Аргументы типа, если они есть, задаются ссылочным выражением метода.

    Во втором поиске, если P 1 , ..., P n не пусто и P 1 является подтипом ReferenceType , то выражение ссылки на метод обрабатывается так, как если бы оно было выражением вызова метода с выражениями аргументов типов P 2 , ..., P n .

    Если при первом поиске создается наиболее конкретный метод, равный static, и набор применимых методов, созданных при втором поиске, не содержит не static методов, то объявление времени компиляции является наиболее заданным методом первый поиск.

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

«Первый поиск» - это прямое соответствие параметров метода типу функционального интерфейса. «Второй поиск» добавляет некоторую гибкость в том смысле, что сам экземпляр объекта из ссылки на метод может служить в качестве первого параметра, совпадающего с функциональным интерфейсом.

В вашем верхнем примере метод m1 равен static, и не существует экземпляра, который мог бы быть неявно первым аргументом, поэтому «второй поиск» здесь не применим.

В нижнем примере getId не является статичным, и применяется «второй поиск» выше. Здесь getId не имеет аргументов, поэтому набор параметров "P2-Pn" пуст. Однако сам объект является неявным первым аргументом, поэтому он соответствует функциональной сигнатуре Function<Transaction, Integer>, ожидаемой методом map в Stream.

0 голосов
/ 14 марта 2019

, но метод apply (T t) в Function имеет один аргумент, а getId () не имеет аргументов

Функция apply принимает аргумент как один типданные и возвращает другой тип данных.В вашем случае это выглядит так:

public Integer apply(Transaction transaction) {
    return transaction.getId();
}

Завершение Function в операции map курса определяет вход и тип вывода для преобразования как:

new Function<Transaction, Integer>() {
    @Override
    public Integer apply(Transaction transaction) {
        return transaction.getId();
    }
}

Напротив, в вашем коде m1 необходим аргумент целочисленного типа, который должен быть передан ему, что приведет к выводу void.Следовательно, ваша реализация соответствует Consumer и может быть представлена ​​как:

Consumer<Integer> consumer = MethodRefTest::m1
...