Справочник по методу Java 8: как определить, какой метод взять?

foo.reverse() фактически меняет элементы в контейнере. reversed() фактически ничего не отменяет, он просто возвращает объект, который можно использовать для итерации по элементам контейнера в обратном порядке. Если это то, что вам нужно, оно часто быстрее, чем наоборот.

6
задан Lorelorelore 13 July 2018 в 10:11
поделиться

3 ответа

NameCreator::createName подразумевает, что либо метод является статическим (вид №1 в таблице ниже), либо цель целевого интерфейса также принимает экземпляр класса (вид # 3, например BiFunction<NameCreator, String, String>). Ваши методы не являются статическими, и поэтому, предположительно, ваша цель не принимает экземпляр, поэтому вы получаете ошибку «Can not solve method». Вероятно, вы захотите использовать ссылку метода на экземпляре (вид # 2). Изнутри класса вы можете использовать:

Function<String, String> func = this::createName

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

NameCreator creator = new NameCreator();
Function<String, String> func = creator::createName;

Что касается использования одно- или двухпараметрической версии , это зависит от того, какой целевой интерфейс используется. Вышеупомянутый будет использовать ваш первый метод, потому что Function<String, String> берет строку и возвращает строку. Например, в следующем функциональном интерфейсе будет использоваться ваш второй метод:

NameCreator creator = new NameCreator();
BiFunction<String, String, String> func = creator::createName;

См. Function , BiFunction и весь пакет java.util.function

Вас также может заинтересовать учебник Java по ссылкам метода , в частности эта часть:


Существует четыре вида ссылок на методы:

Kind                                                   | Example
==============================================================================================
Reference to a static method                           | ContainingClass::staticMethodName
-------------------------------------------------------+--------------------------------------
Reference to an instance method of a particular object | containingObject::instanceMethodName
-------------------------------------------------------+--------------------------------------
Reference to an instance method of an arbitrary object | ContainingType::methodName
of a particular type                                   |
-------------------------------------------------------+--------------------------------------
Reference to a constructor                             | ClassName::new
==============================================================================================
11
ответ дан Michael 17 August 2018 в 13:11
поделиться
  • 1
    Отлично. Поэтому я могу сделать следующее: Consumer<String> consumer = creator::createName. Или Function<String, String> consumer = ... и так далее. Спасибо. – Mulgard 13 July 2018 в 10:19
  • 2
    Ага. Если вам не нужны результирующие строки, вы можете использовать Consumer или BiConsumer, в зависимости от того, какой метод вы хотите. Списки параметров всегда должны точно совпадать, но возвращаемые типы также можно игнорировать. (см. мой ответ здесь ) – Michael 13 July 2018 в 10:21
  • 3
    Вы также можете ссылаться на методы экземпляра с помощью NameCreator::createName, они не обязательно должны быть статическими. Это просто означает, что они принимают дополнительный первый аргумент, который представляет экземпляр. например BiFunction<NameCreator, String, String> func = NameCreator::createName; будет ссылаться на первый метод. – Jorn Vernee 13 July 2018 в 10:29
  • 4
    @JornVernee Правда, это было упрощение. Спасибо, я обновил свой ответ. Надеюсь, он станет более всеобъемлющим. – Michael 13 July 2018 в 10:34

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

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

Например:

interface INameCreator {
    String create(String name);
}

interface INamesCreator {
    String create(String firstName, String lastName);
}

И затем вы можете использовать ссылки метода:

//match NameCreator.createName(String)
INameCreator creator = this::createName //within the class
INameCreator creator = nameCreatorInstance::createName 

И

//match NameCreator.createName(String, String)
INamesCreator creator = this::createName //within the class
INamesCreator creator = nameCreatorInstance::createName

Если этот метод был статическим, вы могли бы использовать синтаксис NameCreator::createName в том же контексте.

4
ответ дан ernest_k 17 August 2018 в 13:11
поделиться

Если вы хотите создать экземпляры типа NameCreator на основе строк, используйте это:

 public static class NameCreator {

    public static String createName(String lastname) {
        return lastname;
    }

    public static String createName(String lastname, String firstName) {
        return lastname + " " + firstName;
    }
}

, а затем выполните следующие вызовы:

  List<String> items = new ArrayList<>();
    //
    items.forEach(NameCreator::createName);//uses the first method
    Map<String, String> map = new HashMap<>();
    //
    map.forEach(NameCreator::createName); //uses the second method
0
ответ дан мυѕτавєւмo 17 August 2018 в 13:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: