Types of method references. Reference to static method. Reference to instance method
Contents
- 1. References to methods. Associating lambda expressions with method references. Types of method references
- 2. Reference to static methods
- 3. Reference to instance methods
- Related topics
Search other websites:
1. References to methods. Associating lambda expressions with method references. Types of method references
If lambda expressions bind to a functional interface, then methods can also bind to a functional interface. A method is associated with a functional interface using a method reference. If a lambda expression can be passed to some method as a parameter, then a method reference can also be passed as a parameter. Using this reference, you can access the method without calling it.
There are 4 types of method references in Java:
- references to static methods;
- references to instance methods;
- references to constructors;
- references to generic (template) methods.
⇑
2. Reference to static methods
2.1. General form of references to static methods. Delimiter ::
In Java, you can declare static method references. A reference to a static method can be passed to some method and used there to call a static method.
The general form of declaring a reference to a static method is as follows:
class_name::method_name
The :: delimiter was introduced in JDK 8 to define a method reference.
For example. If class A declares a static method named Method()
class A { // ... static return_type Method(parameters) { // ... } }
then the reference to this method will be as follows
A::Method
⇑
2.2. Examples of references to static methods
2.2.1. Reference to the static method for calculating the volume of a sphere
Task. Develop a static method that takes the radius of a sphere and calculates it’s volume. Implement the passing of the method for calculating the volume of a sphere to another method as a parameter. Test the method.
Solution. When solving this problem, you need to develop the following elements:
- functional interface ICalcFigure. The interface declares a single method, Volume(), which receives a double number and returns a double value;
- the CalcVolume() class, which declares the static SphereVolume() method. The method gets the radius of the ball (double) and returns the volume of the ball (double);
- the FigureOperation class, which declares the Volume() method. This method takes two parameters. The first parameter is a reference to the ICalcFigure interface. The second parameter is the radius of the circle. By reference to ICalcFigure, a static method for calculating the volume of a sphere will be passed.
The text of the program for solving this problem is as follows.
// Reference to a static method that calculates the volume of a sphere // 1. A functional interface that defines a method // that takes a double as a parameter and returns a double result interface ICalcFigure { double Volume(double radius); } // 2. A class that defines a static method for calculating the volume of a sphere class CalcVolume { static double SphereVolume(double radius) { // return the volume of a sphere return 4.0/3.0*Math.PI*radius*radius*radius; } } // 3. The class in which the method is defined that receives a reference to the functional interface class FigureOperation { double Volume(ICalcFigure ref, double radius) { return ref.Volume(radius); } } // 4. Class demonstrating the use of a static method reference public class RefMethod { public static void main(String[] args) { // Calculate the volume of a sphere // 1. Declare an instance of the FigureOperation class FigureOperation fo = new FigureOperation(); // 2. Call the Volume method and pass it a reference to the static method // Calculate the volume of a sphere of radius 5.0 double volume = fo.Volume(CalcVolume::SphereVolume, 5.0); // 3. Вывести результат System.out.println("volume = " + volume); } }
The result of the program
volume = 523.5987755982989
⇑
2.2.2. Reference to generalized static method for reversing an array of numbers
Task. Develop a generic static ReverseNumbers() method that implements reversing an array of numbers. Implement passing a method to another method by reference.
Solution. The sequence of steps to be followed to solve the problem:
- declare a generic (template) functional interface IArrayFunction. The interface must define the Function() method, which receives an array of numbers as a parameter and returns an array of numbers (using the return statement);
- declare the ProcessArray class with a generic static method ProcessArrayReverse();
- declare the DemoRefMethods class in which to implement the template method DemoReverse(). In the DemoReverse() method, use the IArrayFunction functional interface reference to call the Function() method;
- in the main() function, demonstrate passing the static ProcessArrayReverse() method to the DemoReverse() method.
The program text that solves this problem is as follows
// Reference to static method // 1. Generalized functional interface interface IArrayFunction<T extends Number> { // A method that receives an array of type T and returns an array of type T T[] Function(T[] array); } // 2. A class that contains a generic static method that returns an array of numbers class ProcessArray { public static <T extends Number> T[] ProcessArrayReverse(T[] array) { T tmp; for (int i=0; i<array.length/2; i++) { tmp = array[i]; array[i] = array[array.length - 1 - i]; array[array.length - 1 - i] = tmp; } return array; } } // 3. The class in which the method is defined that receives a reference to the functional interface class DemoRefMethods { // A method that receives a reference to the functional interface IArrayFunction<T> <T extends Number> T[] DemoReverse(IArrayFunction<T> ref, T[] array) { return ref.Function(array); } } // 4. Class demonstrating the use of a reference to static method public class RefMethod { public static void main(String[] args) { // Implement reversing an array of integers // 1. Declare an instance of the DemoRefMethods class DemoRefMethods obj = new DemoRefMethods(); // 2. Testing array Integer AI[] = { 1, 3, 5, 8, 4, 2 }; System.out.println("Array AI: "); for (int i=0; i<AI.length; i++) System.out.print(" " + AI[i]); System.out.println(); // 3. Pass static method ProcessArray.ProcessArrayReverse() to obj.DemoReverse() method Integer AI2[] = obj.DemoReverse(ProcessArray::ProcessArrayReverse, AI); // 4. Print the result - array AI2 System.out.println("Array AI2: "); for (int i=0; i<AI2.length; i++) System.out.print(" " + AI2[i]); System.out.println(); } }
The result of the program
Array AI: 1 3 5 8 4 2 Array AI2: 2 4 8 5 3 1
⇑
3. Reference to instance methods
3.1. The general form of a reference to the instance methods
One of two general forms is used to declare a reference to the instance method:
instance_name::method_name class_name::method_name
Otherwise, an instance method is specified alongside any object of the given class, not just the specified object.
⇑
3.2. Examples of using instance method references
3.2.1. Reference to methods that perform actions on complex numbers
Task. Demonstrate passing to a certain method of a class of methods for summing and subtracting complex numbers.
Solution. To solve the problem in the program, it is necessary to develop the following elements (components).
1. Class Complex that defines a complex number
class Complex { // Real and imaginary parts of a complex number public double re; public double im; ... }
2. Functional interface for operating the Complex type
interface IFunction { // A method that operates on complex numbers of type Complex Complex Function(Complex c1, Complex c2); }
The Function() method is declared in the functional interface. The method signature specifies the receiving of two complex numbers and return a complex number. Such a signature can be suitable for operations of addition, subtraction, multiplication, division of complex numbers, and other operations.
3. A class that contains the actual methods for processing complex numbers (summation, subtraction).
class ProcessComplex { // The summation of complex numbers Complex Add(Complex c1, Complex c2) { ... } // Subtraction of complex numbers Complex Sub(Complex c1, Complex c2) { ... } }
4. A class containing a method that receives a reference to an instance method. In our case, you need to pass the Add () and Sub() methods of an instance of the ProcessComplex class.
class DemoRefMethods { // This method will be passed a reference to the Add() and Sub() // methods of an instance of the ProcessComplex class. Complex RefMethod(IFunction ref, Complex c1, Complex c2) { ... } }
5. Class that demonstrates the use of an instance method reference
// 5. A class that demonstrates the use of an instance method reference public class RefMethod { public static void main(String[] args) { ... } }
Below is the text of the solution to the task.
// Reference to the instance method // 1. Class that defines a complex number class Complex { // Real and imaginary parts of a complex number public double re; public double im; // Constructor public Complex(double _re, double _im) { re = _re; im = _im; } // Method that prints a complex number void Print(String text) { System.out.print(text); System.out.print(re); if (im>0) System.out.print("+"); System.out.println(im); } } // 2. A functional interface that operates on the Complex type interface IFunction { // Method operating on complex numbers of type Complex Complex Function(Complex c1, Complex c2); } // 3. A class that contains methods for handling complex numbers class ProcessComplex { // Summing complex numbers Complex Add(Complex c1, Complex c2) { Complex c3 = new Complex(c1.re+c2.re, c1.im+c2.im); return c3; } // Subtraction of complex numbers Complex Sub(Complex c1, Complex c2) { Complex c3 = new Complex(c1.re-c2.re, c1.im-c2.im); return c3; } } // 4. The class in which the method is defined, which receives // a reference to the functional interface IFunction class DemoRefMethods { // A method that gets complex numbers and a reference // to the functional interface IFunction. // This method will be passed a reference to the method // of an instance of the ProcessComplex class. Complex RefMethod(IFunction ref, Complex c1, Complex c2) { Complex c3; c3 = ref.Function(c1, c2); return c3; } } // 5. Class that demonstrates the use of an instance method reference public class RefMethod { public static void main(String[] args) { // Implement summation and subtraction of complex numbers // 1. Declare the instance of ProcessComplex Class ProcessComplex obj1 = new ProcessComplex(); // 2. Declare an instance of the DemoRefMethods class DemoRefMethods objDemo = new DemoRefMethods(); // 3. Create complex numbers for testing Complex c1 = new Complex(5, -8); Complex c2 = new Complex(3, 4); c1.Print("c1 = "); c2.Print("c2 = "); // 4. Pass to the objDemo.RefMethod() method a reference // to the obj1.Add () method and display the result Complex c3 = objDemo.RefMethod(obj1::Add, c1, c2); c3.Print("c3 = c1 + c2 = "); // 5. Demonstrate subtraction of complex numbers Complex c4; // pass obj1::Sub to RefMethod() c4 = objDemo.RefMethod(obj1::Sub, c1, c2); c4.Print("c4 = c1 - c2 = "); } }
The result of the program
c1 = 5.0-8.0 c2 = 3.0+4.0 c3 = c1 + c2 = 8.0-4.0 c4 = c1 - c2 = 2.0-12.0
⇑
3.2.2. A reference to the templated method of instance.
Task. Implement a class containing the following generic (template) methods for working with arrays:
- calculating the sum of array elements;
- calculation the average of array.
Demonstrate calling array processing methods using the method of passing a reference to an instance method as a parameter.
Solution.
// Reference to the generic instance method // 1. Generalized (templated) functional interface interface IFuncArray<T extends Number> { // A method that receives an array of type T and returns a double double FuncArray(T[] array); } // 2. A class containing methods for processing arrays class ProcessArray<T extends Number> { // The sum of array items double Sum(T[] array) { double sum = 0; for (T value : array) sum += value.doubleValue(); return sum; } // The average of array items double Avg(T[] array) { double avg = 0; for (T value : array) avg += value.doubleValue(); return avg/array.length; } } // 3. A class that contains a templated method // that returns a reference to the instance method class ClassOperation { <T extends Number> double Operation(IFuncArray<T> ref, T[] array) { // invoke method of IFuncArray interface double result = ref.FuncArray(array); return result; } } // 4. A class that demonstrates a reference to the instance method public class RefMethod { public static void main(String[] args) { // 1. Declare the instance of ClassOperation class ClassOperation Op = new ClassOperation(); // 2. Declare a reference to ProcessArray<T> class ProcessArray<Integer> Array = new ProcessArray<Integer>(); // 3. Prepare an array of integers for processing and display it Integer[] AI = { 2, 4, 8, -1, 3, -5 }; System.out.print("AI = "); for (int t : AI) System.out.print(t + " "); System.out.println(); // 4. Calculate the arithmetic average of an AI // by passing Array.Avg() to Op.Operation () double average = Op.Operation(Array::Avg, AI); System.out.println("average = " + average); // 5. Calculate the sum of array AI items. // To do this, you need to pass the Array.Sum() method to Op.Operation() double sum = Op.Operation(Array::Sum, AI); System.out.println("sum = " + sum); } }
As you can see from the main() function code, the Avg() and Sum() methods of the Array instance are passed by calling the only Op.Operation() method.
... double average = Op.Operation(Array::Avg, AI); ... double sum = Op.Operation(Array::Sum, AI); ...
The difference in calls is in passing the first parameter, which is a reference to the instance method. In the first case, an instance method is passed that calculates the arithmetic average using the following syntax
Array::Avg
Otherwise, an instance method is passed
Array::Sum
which calculates the sum.
After running for execution, the program will print the following result
AI = 2 4 8 -1 3 -5 average = 1.8333333333333333 sum = 11.0
⇑
Related topics
⇑