Java конструкторы с ссылками

Rukovodstvo

статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.

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

Введение Самым сладким синтаксическим сахаром [https://en.wikipedia.org/wiki/Syntactic_sugar], добавленным в Java до сих пор, безусловно, являются лямбда-выражения [/ lambda-expressions-in-java]. Java — многословный язык, который может мешать производительности и удобочитаемости. Сокращение шаблонного и повторяющегося кода всегда было популярной задачей среди разработчиков Java, и обычно требуется чистый, читаемый, краткий код. Лямбда-выражения устранили необходимость набирать громоздкую шаблонную cod

Вступление

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

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

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

Эти выражения широко используются в Java Streams API и в среде Spring WebFlux для создания реактивных динамических приложений.

Еще одна, действительно полезная функция, добавленная в Java 8, — это ссылки на методы , которые делают лямбда-выражения намного более краткими и простыми, вызывая (ссылаясь) на методы с использованием имени метода, когда лямбда-выражение использовалось бы просто для вызова метод.

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

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

Они состоят из двух частей:

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

 someCodeChain.subscribe(System.out::println); 

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

 public class Employee < private int id; private String name; private int wage; private String position; // Constructor, getters and setters @Override public String toString() < return "Name: " + name + ", Wage: " + wage + ", Position: " + position; >public int compareTo(Employee employee) < if (this.wage else < return -1; >> > 

Если мы создали этот класс в коллекции, такие как ArrayList , мы не могли сортировать его с помощью утилиты метод .sort() , так как он не реализует Comparable интерфейс.

Читайте также:  Css style all borders

Что мы можем сделать, так это определить new Comparator для этих объектов при вызове .sort() :

 Employee emp1 = new Employee(1, "David", 1200, "Developer"); Employee emp2 = new Employee(2, "Tim", 1500, "Developer"); Employee emp3 = new Employee(3, "Martha", 1300, "Developer"); ArrayList employeeList = new ArrayList<>(); employeeList.add(emp1); employeeList.add(emp2); employeeList.add(emp3); Collections.sort(employeeList, new Comparator() < public int compare(Employee emp1, Employee emp2) < return emp1.compareTo(emp2); >>); System.out.println(employeeList); 
 [Name: Tim, Wage: 1500, Position: Developer, Name: Martha, Wage: 1300, Position: Developer, Name: David, Wage: 1200, Position: Developer] 

Здесь анонимный класс ( Comparator ) определяет критерии сравнения. Мы можем сделать его намного проще и короче, используя лямбда-выражение:

 Collections.sort(employeeList, (e1, e2) -> e1.compareTo(e2)); 

Выполнение этого фрагмента кода даст:

 [Name: Tim, Wage: 1500, Position: Developer, Name: Martha, Wage: 1300, Position: Developer, Name: David, Wage: 1200, Position: Developer] 

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

 Collections.sort(employeeList, Employee::compareTo); 
 [Name: Tim, Wage: 1500, Position: Developer, Name: Martha, Wage: 1300, Position: Developer, Name: David, Wage: 1200, Position: Developer] 

Типы ссылок на методы

Ссылки на методы можно использовать в нескольких различных сценариях:

  • Статические методы: Class::staticMethodName
  • Методы экземпляра конкретных объектов: object::instanceMethodName
  • Методы экземпляра объектов арбитража: Class::methodName
  • Справочник конструктора: Class::new

Давайте рассмотрим все эти типы на нескольких простых примерах.

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

Вы можете ссылаться на любой static метод класса, просто вызывая содержащий его класс с именем метода.

Давайте определим класс static методом, а затем будем ссылаться на него из другого класса:

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

 public class ClassB < public static void main(String[] args) < ListintegerList = new ArrayList<>(); integerList.add(new Double(5)); integerList.add(new Double(2)); integerList.add(new Double(6)); integerList.add(new Double(1)); integerList.add(new Double(8)); integerList.add(new Double(9)); integerList.forEach(ClassA::raiseToThePowerOfTwo); > > 

Выполнение этого фрагмента кода даст:

Читайте также:  Java конец строки метод

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

Методы экземпляров отдельных объектов

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

Чаще всего это иллюстрируется настраиваемым компаратором. Мы будем использовать тот же Employee и тот же список, чтобы выделить разницу между этими двумя:

 public class Employee < private int id; private String name; private int wage; private String position; // Constructor, getters and setters @Override public String toString() < return "Name: " + name + ", Wage: " + wage + ", Position: " + position; >public int compareTo(Employee employee) < if (this.wage else < return -1; >> > 

Теперь давайте определим CustomComparator :

 public class CustomComparator < public int compareEntities(Employee emp1, Employee emp2) < return emp1.compareTo(emp2); >> 

И, наконец, давайте заполним список и отсортируем его:

 Employee emp1 = new Employee(1, "David", 1200, "Developer"); Employee emp2 = new Employee(2, "Tim", 1500, "Developer"); Employee emp3 = new Employee(3, "Martha", 1300, "Developer"); ArrayList employeeList = new ArrayList<>(); employeeList.add(emp1); employeeList.add(emp2); employeeList.add(emp3); // Initializing our CustomComparator CustomComparator customComparator = new CustomComparator(); // Instead of making a call to an arbitrary Employee // we're now providing an instance and its method Collections.sort(employeeList, customComparator::compareEntities); System.out.println(employeeList); 

Запуск этого кода также даст:

 [Name: Tim, Wage: 1500, Position: Developer, Name: Martha, Wage: 1300, Position: Developer, Name: David, Wage: 1200, Position: Developer] 

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

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

Методы экземпляров произвольных объектов

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

Хотя, на всякий случай, поскольку этот подход используется очень часто, давайте рассмотрим другой пример:

 List integerList = new ArrayList<>(); integerList.add(new Integer(5)); integerList.add(new Integer(2)); integerList.add(new Integer(6)); integerList.add(new Integer(1)); integerList.add(new Integer(8)); integerList.add(new Integer(9)); // Referencing the non-static compareTo method from the Integer class Collections.sort(integerList, Integer::compareTo); // Referencing static method integerList.forEach(System.out::print); 

Выполнение этого фрагмента кода даст:

Читайте также:  Питон загрузить файл csv

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

 Collections.sort(integerList, (Integer a, Integer b) -> a.compareTo(b)); 

Здесь различие более очевидно. Если бы мы вызывали static метод, это выглядело бы так:

 Collections.sort(integerList, (Integer a, Integer b) -> SomeClass.compare(a, b)); 

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

Вы можете ссылаться на конструктор класса так же, как и на static метод.

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

 // Classic instantiation Employee employee = new Employee(); // Constructor reference Employee employee2 = Employe::new; 

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

 Stream stream = names.stream().map(Employee::new); 

Из-за потока имен, если присутствует конструктор Employee(String name) , он будет использоваться.

Другой способ использования ссылок на конструкторы — это когда вы хотите отобразить поток в массив, сохранив при этом конкретный тип. Если бы вы просто сопоставили его, а затем вызывали toArray() , вы бы получили массив Object s вместо вашего конкретного типа.

Если мы попробовали, скажем:

 Employee[] employeeArray = employeeList.toArray(); 

Конечно, мы столкнемся с ошибкой компилятора, поскольку мы .toArray() возвращает массив Object s. Кастинг тоже не поможет:

 Employee[] employeeArray = (Employee[]) employeeList.toArray(); 

Но на этот раз это будет исключение времени выполнения — ClassCastException .

Этого можно избежать с помощью:

 // Making a list of employees List employeeList = Arrays.asList("David", "Scott"); // Mapping a list to Employee objects and returning them as an array Employee[] employeeArray = employeeList.stream().map(Employee::new).toArray(Employee[]::new); // Iterating through the array and printing information for (int i = 0; i

И с этим мы получаем результат:

 Name: David, Wage: 0, Position: null Name: Scott, Wage: 0, Position: null 

Заключение

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

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

Licensed under CC BY-NC-SA 4.0

Источник

Оцените статью