Java передача ссылки на метод

Ссылки на методы. Виды ссылок на методы. Ссылка на статический метод. Ссылка на метод экземпляра

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

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

В Java различают 4 вида ссылок на методы:

  • ссылки на статические методы;
  • ссылки на методы экземпляра;
  • ссылки на конструкторы;
  • ссылки на обобщенные (шаблонные) методы.
2. Ссылка на статические методы
2.1. Общая форма ссылок на статические методы. Разделитель ::

В языке Java можно объявлять ссылки на статические методы. Ссылка на статический метод может быть передана в некоторый метод и там использована для вызова статического метода.

Общая форма объявления ссылки на статический метод следующая:

имя_класса::имя_метода

Разделитель :: внедрен в версии JDK 8 для определения ссылки на метод.

Например. Если в классе A объявлен статический метод с именем Method()

class A < // .  static return_type Method(parameters) < // . > >

то ссылка на этот метод будет следующей

2.2. Примеры ссылок на статические методы
2.2.1. Ссылка на статический метод вычисления объема шара

Условие задачи. Разработать статический метод, который получает радиус шара и вычисляет объем шара. Реализовать передачу метода вычисления объема шара в другой метод в качестве параметра. Провести тестирование метода.

Решение. При решении данной задачи нужно разработать следующие элементы:

  • функциональный интерфейс ICalcFigure . В интерфейсе объявляется единственный метод Volume() , который получает число типа double и возвращает значение типа double ;
  • класс CalcVolume() , в котором объявляется статический метод SphereVolume() . Метод получает радиус шара ( double ) и возвращает объем шара ( double )
  • класс FigureOperation , в котором объявляется метод Volume() . Этот метод получает два параметра. Первый параметр является ссылкой на интерфейс ICalcFigure . Второй параметр — радиус окружности. По ссылке на ICalcFigure будет передан статический метод вычисления объема шара.

Текст программы, решения данной задачи, следующий.

Результат выполнения программы

Array AI: 1 3 5 8 4 2 Array AI2: 2 4 8 5 3 1
3. Ссылка на методы экземпляра
3.1. Общая форма ссылки на методы экземпляра

Чтобы объявить ссылку на метод экземпляра используется одна из двух общих форм:

имя_экземпляра::имя_метода имя_класса::имя_метода

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

Читайте также:  Getting options value in javascript
3.2. Примеры использования ссылок на методы экземпляра
3.2.1. Ссылка на методы, выполняющие действия над комплексными числами

Условие задачи. Продемонстрировать передачу в некоторый метод класса методов суммирования и вычитания комплексных чисел.

Решение. Для решения задачи в программе необходимо разработать следующие элементы (составляющие).

1. Класс Complex , определяющий комплексне число

class Complex < // Вещественная и мнимая части комплексного числа  public double re;  public double im; . >

2. Функциональный интерфейс для оперирования типом Complex

interface IFunction < // Метод, который оперирует комплексными числами типа Complex Complex Function(Complex c1, Complex c2); >

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

3. Класс, содержащий собственно методы обработки комплексных чисел (суммирование, вычитание).

class ProcessComplex < // Суммирование комплексных чисел Complex Add(Complex c1, Complex c2) < . > // Вычитание комплексных чисел Complex Sub(Complex c1, Complex c2) < . >>

4. Класс, содержащий метод, который получает ссылку на метод экземпляра. В нашем случае нужно передавать методы Add() и Sub() экземпляра класса ProcessComplex .

class DemoRefMethods < // В этот метод будет передаваться ссылка на методы Add() и Sub() // экземпляра класса ProcessComplex Complex RefMethod(IFunction ref, Complex c1, Complex c2) < . >>

5. Класс, демонстрирующий использование ссылки на метод экземпляра

// 5. Класс, который демонстрирует использование ссылки на метод экземпляра public class RefMethod <  public static void main(String[] args) < . >>

Ниже приведен текст решения задачи.

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

В другом случае передается метод экземпляра

После запуска на выполнение программа выдаст следующий результат

AI = 2 4 8 -1 3 -5 average = 1.8333333333333333 sum = 11.0

Связанные темы

Источник

Method References

You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

Consider again the Person class discussed in the section Lambda Expressions:

public class Person < // . LocalDate birthday; public int getAge() < // . >public LocalDate getBirthday() < return birthday; >public static int compareByAge(Person a, Person b) < return a.birthday.compareTo(b.birthday); >// . >

Suppose that the members of your social networking application are contained in an array, and you want to sort the array by age. You could use the following code (find the code excerpts described in this section in the example MethodReferencesTest ):

Person[] rosterAsArray = roster.toArray(new Person[roster.size()]); class PersonAgeComparator implements Comparator  < public int compare(Person a, Person b) < return a.getBirthday().compareTo(b.getBirthday()); >> Arrays.sort(rosterAsArray, new PersonAgeComparator());

The method signature of this invocation of sort is the following:

static void sort(T[] a, Comparator c)

Notice that the interface Comparator is a functional interface. Therefore, you could use a lambda expression instead of defining and then creating a new instance of a class that implements Comparator :

Arrays.sort(rosterAsArray, (Person a, Person b) -> < return a.getBirthday().compareTo(b.getBirthday()); >);

However, this method to compare the birth dates of two Person instances already exists as Person.compareByAge . You can invoke this method instead in the body of the lambda expression:

Arrays.sort(rosterAsArray, (a, b) -> Person.compareByAge(a, b) );

Because this lambda expression invokes an existing method, you can use a method reference instead of a lambda expression:

Arrays.sort(rosterAsArray, Person::compareByAge);

The method reference Person::compareByAge is semantically the same as the lambda expression (a, b) -> Person.compareByAge(a, b) . Each has the following characteristics:

  • Its formal parameter list is copied from Comparator.compare , which is (Person, Person) .
  • Its body calls the method Person.compareByAge .
Читайте также:  Время работы скрипта python

Kinds of Method References

There are four kinds of method references:

Kind Syntax Examples
Reference to a static method ContainingClass::staticMethodName Person::compareByAge
MethodReferencesExamples::appendStrings
Reference to an instance method of a particular object containingObject::instanceMethodName myComparisonProvider::compareByName
myApp::appendStrings2
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName String::compareToIgnoreCase
String::concat
Reference to a constructor ClassName::new HashSet::new

The following example, MethodReferencesExamples , contains examples of the first three types of method references:

import java.util.function.BiFunction; public class MethodReferencesExamples < public static T mergeThings(T a, T b, BiFunction merger) < return merger.apply(a, b); >public static String appendStrings(String a, String b) < return a + b; >public String appendStrings2(String a, String b) < return a + b; >public static void main(String[] args) < MethodReferencesExamples myApp = new MethodReferencesExamples(); // Calling the method mergeThings with a lambda expression System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", (a, b) ->a + b)); // Reference to a static method System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", MethodReferencesExamples::appendStrings)); // Reference to an instance method of a particular object System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", myApp::appendStrings2)); // Reference to an instance method of an arbitrary object of a // particular type System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", String::concat)); > >

All the System.out.println() statements print the same thing: Hello World!

BiFunction is one of many functional interfaces in the java.util.function package. The BiFunction functional interface can represent a lambda expression or method reference that accepts two arguments and produces a result.

Reference to a Static Method

The method references Person::compareByAge and MethodReferencesExamples::appendStrings are references to a static method.

Reference to an Instance Method of a Particular Object

The following is an example of a reference to an instance method of a particular object:

class ComparisonProvider < public int compareByName(Person a, Person b) < return a.getName().compareTo(b.getName()); >public int compareByAge(Person a, Person b) < return a.getBirthday().compareTo(b.getBirthday()); >> ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

The method reference myComparisonProvider::compareByName invokes the method compareByName that is part of the object myComparisonProvider . The JRE infers the method type arguments, which in this case are (Person, Person) .

Читайте также:  Work with lists in python

Similarly, the method reference myApp::appendStrings2 invokes the method appendStrings2 that is part of the object myApp . The JRE infers the method type arguments, which in this case are (String, String) .

Reference to an Instance Method of an Arbitrary Object of a Particular Type

The following is an example of a reference to an instance method of an arbitrary object of a particular type:

String[] stringArray = < "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" >; Arrays.sort(stringArray, String::compareToIgnoreCase);

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b) , where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b) .

Similarly, the method reference String::concat would invoke the method a.concat(b) .

Reference to a Constructor

You can reference a constructor in the same way as a static method by using the name new . The following method copies elements from one collection to another:

public static , DEST extends Collection> DEST transferElements( SOURCE sourceCollection, Supplier collectionFactory) < DEST result = collectionFactory.get(); for (T t : sourceCollection) < result.add(t); >return result; >

The functional interface Supplier contains one method get that takes no arguments and returns an object. Consequently, you can invoke the method transferElements with a lambda expression as follows:

Set rosterSetLambda = transferElements(roster, () -> < return new HashSet<>(); >);

You can use a constructor reference in place of the lambda expression as follows:

Set rosterSet = transferElements(roster, HashSet::new);

The Java compiler infers that you want to create a HashSet collection that contains elements of type Person . Alternatively, you can specify this as follows:

Set rosterSet = transferElements(roster, HashSet::new);

Previous page: Lambda Expressions
Next page: When to Use Nested Classes, Local Classes, Anonymous Classes, and Lambda Expressions

Источник

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