Рубрики
Без рубрики

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

Краткий и практический обзор ссылок на методы в Java.

Автор оригинала: baeldung.

1. Обзор

Одним из самых желанных изменений в Java 8 стало введение лямбда-выражений , поскольку они позволяют нам отказаться от анонимных классов, значительно сокращая шаблонный код и улучшая читаемость.

Ссылки на методы-это особый тип лямбда-выражений . Они часто используются для создания простых лямбда-выражений, ссылаясь на существующие методы.

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

  • Статические методы
  • Методы экземпляра конкретных объектов
  • Методы экземпляра произвольного объекта определенного типа
  • Конструктор

В этом уроке мы рассмотрим ссылки на методы в Java.

2. Ссылка на статический метод

Мы начнем с очень простого примера, заглавной буквы и печати списка Строк :

List messages = Arrays.asList("hello", "baeldung", "readers!");

Мы можем достичь этого, используя простое лямбда-выражение, вызывающее метод StringUtils.capitalize() напрямую:

messages.forEach(word -> StringUtils.capitalize(word));

Или мы можем использовать ссылку на метод, чтобы просто обратиться к статическому методу capitalize :

messages.forEach(StringUtils::capitalize);

Обратите внимание, что ссылки на методы всегда используют :: оператор.

3. Ссылка на Метод экземпляра конкретного объекта

Чтобы продемонстрировать этот тип ссылки на метод, рассмотрим два класса:

public class Bicycle {

    private String brand;
    private Integer frameSize;
    // standard constructor, getters and setters
}

public class BicycleComparator implements Comparator {

    @Override
    public int compare(Bicycle a, Bicycle b) {
        return a.getFrameSize().compareTo(b.getFrameSize());
    }

}

И давайте создадим Велосипедный компаратор объект для сравнения размеров велосипедной рамы:

BicycleComparator bikeFrameSizeComparator = new BicycleComparator();

Мы могли бы использовать лямбда-выражение для сортировки велосипедов по размеру кадра, но нам нужно будет указать два велосипеда для сравнения:

createBicyclesList().stream()
  .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));

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

createBicyclesList().stream()
  .sorted(bikeFrameSizeComparator::compare);

Ссылка на метод намного чище и читабельнее, так как наше намерение ясно показано в коде.

4. Ссылка на Метод экземпляра Произвольного объекта Определенного типа

Этот тип ссылки на метод аналогичен предыдущему примеру, но без необходимости создавать пользовательский объект для выполнения сравнения.

Давайте создадим Целочисленный список, который мы хотим отсортировать:

List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);

Если мы используем классическое лямбда-выражение, оба параметра должны быть явно переданы, в то время как использование ссылки на метод намного проще:

numbers.stream()
  .sorted((a, b) -> a.compareTo(b));
numbers.stream()
  .sorted(Integer::compareTo);

Несмотря на то, что это все еще однострочная ссылка, ссылку на метод гораздо легче читать и понимать.

5. Ссылка на конструктор

Мы можем ссылаться на конструктор так же, как мы ссылались на статический метод в нашем первом примере. Разница лишь в том, что мы будем использовать ключевое слово new .

Давайте создадим Велосипед массив из Строки списка с разными брендами:

List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");

Во-первых, мы добавим новый конструктор в наш класс Bicycle :

public Bicycle(String brand) {
    this.brand = brand;
    this.frameSize = 0;
}

Затем мы используем наш новый конструктор из ссылки на метод и создадим массив Bicycle из исходного String списка:

bikeBrands.stream()
  .map(Bicycle::new)
  .toArray(Bicycle[]::new);

Обратите внимание, как мы вызвали оба конструктора Bicycle и Array , используя ссылку на метод, что придало нашему коду гораздо более лаконичный и четкий вид.

6. Дополнительные примеры и ограничения

Как мы уже видели, ссылки на методы-отличный способ сделать наш код и намерения очень ясными и читабельными. Однако мы не можем использовать их для замены всех видов лямбда-выражений, поскольку они имеют некоторые ограничения.

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

Давайте рассмотрим пример этого ограничения:

createBicyclesList().forEach(b -> System.out.printf(
  "Bike brand is '%s' and frame size is '%d'%n",
  b.getBrand(),
  b.getFrameSize()));

Этот простой случай не может быть выражен ссылкой на метод, поскольку метод printf в нашем случае требует 3 параметров, а использование createBicyclesList().forEach() позволит ссылке на метод вывести только один параметр (объект Bicycle ).

Наконец, давайте рассмотрим, как создать функцию без операции, на которую можно ссылаться из лямбда-выражения.

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

Во-первых, давайте создадим метод Вообще ничего не делать :

private static  void doNothingAtAll(Object... o) {
}

Поскольку это метод varargs, он будет работать в любом лямбда-выражении, независимо от объекта ссылки или количества выведенных параметров.

А теперь давайте посмотрим на это в действии:

createBicyclesList()
  .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));

7. Заключение

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

Весь код, представленный в этой статье, доступен на GitHub .