The :: operator refers to a method reference.
A method reference is a simplified way of writing a lambda expression in order to call a method. Method references allow you to call a method by mentioning its name. The syntax for a method reference is as follows:
Object :: methodName
There are four ways to use a method reference:
- A method reference to a static method.
- A method reference to an instance method of an object.
- A method reference to instance methods of an arbitrary object of a particular type.
- A method reference to a constructor.
METHOD REFERENCE TO A STATIC METHOD
Let's take a look at the code snippet below:
import java.util.function.BiFunction;
class Maths {
public static int printAddition(int x, int y){
return x + y;
}
}
public class Main {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> addition = Maths::printAddition;
int result = addition.apply(2, 4);
System.out.println("The result is: " + result);
}
}
The outcome is:
The result is: 6
- We have a non-static inner class called Maths
- Inside this inner class we have a static method that given x and y returns back the addition between x and y
- Then we have the Main public class where we declare the main method so that we can execute our program
- Inside the main method we have the BiFunction functional interface.
- To explain this better, BiFunction is a functional interface that takes three parameters: T, U, and R. In our case, T and U are 2 and 4 respectively, which are both Integers. Our R is 6, which is again an Integer. In short, we are saying take a first Integer argument, then take a second Integer argument, and give me a result of Integer type. You can read more about BiFunction and other functional interfaces here.
- This is where we encounter the method reference. We take the name of the inner class (Maths), the :: operator, and the name of the method printAddition.
- The BiFunction uses the method apply()to apply the method to the two arguments. In our case, our arguments are 2 and 4. We assigned this operation to the result variable.
In the end, we print the outcome to the console.
METHOD REFERENCE TO AN INSTANCE METHOD OF AN OBJECT
@java.lang.FunctionalInterface
interface Maths {
void printAddition();
}
public class Main {
public void printMessage(){
System.out.println("Method reference to an instance method of an object");
}
public static void main(String[] args) {
Main main = new Main();
Maths reference = main::printMessage;
reference.printAddition();
}
}
The outcome is:
Method reference to an instance method of an object
- We start our program with the functional interface Maths, which contains a printAddition() method.
- We have the Main public class where there is a printMessage() method that prints out a message on the console.
- In our main method, we instantiate an object called main.
- We use the method reference on the object that we created earlier.
- We call the printAddition() via the reference variable of type Maths.
METHOD REFERENCE TO AN INSTANCE METHOD OF AN ARBITRARY OBJECT OF A PARTICULAR TYPE
Let's consider the following program:
package com.maddy;
public class Subject {
private String name;
private String assignment;
public Subject(String name, String assignment) {
this.name = name;
this.assignment = assignment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAssignment() {
return assignment;
}
public void setAssignment(String assignment) {
this.assignment = assignment;
}
public void print(){
System.out.println("The name of the subject is: " + name + " and your assignment is: " + assignment);
}
}
And this one as well:
package com.maddy;
import java.util.ArrayList;
import java.util.List;
public class SubjectDemo {
public static void main(String[] args) {
List<Subject> subjects = new ArrayList<Subject>();
subjects.add(new Subject("English", "Shakespeare"));
subjects.add(new Subject("Geography", "Europe"));
subjects.add(new Subject("History", " The Romans"));
subjects.forEach(Subject::print);
}
}
The outcome is:
The name of the subject is: English and your assignment is: Shakespeare
The name of the subject is: Geography and your assignment is: Europe
The name of the subject is: History and your assignment is: The Romans
Let's examine what is happening here:
- We created a class Subject that has two fields, the name of the subject, an assignment, a constructor and getters and setters. We also added a method that prints the name of the subject and its assignment.
- Then we have a class called SubjectDemo where we created a list of Subject objects with some values.
- We used the method reference to say that we want to apply the print method from the Subject class on each subject. A method reference can be called on an arbitrary method because in this case, we called the print method on all the subjects, not a particular one.
METHOD REFERENCE ON A CONSTRUCTOR
Let's look at the following code snippet:
package com.maddy;
@java.lang.FunctionalInterface
interface Geography {
void print(String message);
}
class Test{
public Test(String test) {
System.out.println(test);
}
}
public class GeographyTest {
public static void main(String[] args) {
Geography geography = Test::new;
geography.print("Hello student! You've been assigned a Geography test. :) ");
}
}
The outcome is:
Hello student! You've been assigned a Goography test. :)
Here, we're:
- Creating a functional interface called Geography in which there is a method that prints a message;
- An inner class called Test with a constructor that initializes a test String and prints out the test itself when an object is created.
- In our main method, we use a method reference on the Test class constructor.
- Finally, we print out a message.
Easy to understand and good explanation with example
ReplyDelete