Method references in Java are a feature that was introduced in Java 8. They provide a way to refer to a method without actually executing it. They are often used in conjunction with Java’s functional programming features, such as Streams and Lambdas, where a method to be executed is often expected as a parameter.
The syntax for a method reference is the name of the class (or the name of an object), followed by ::
and the method’s name. Here’s an example:
List<String> words = Arrays.asList("Hello", "Method", "References", "In", "Java");
// Let's use a method reference to print each word in the list
words.forEach(System.out::println);
In the above code, System.out::println
is a method reference. The forEach
method expects a lambda that takes a parameter and does something with it. Here, the println
method of the System.out
class is being referenced, and it will be used to print each word in the list.
There are four types of method references in Java:
- Static method reference: They refer to the static methods of a class. For example,
ClassName::staticMethodName
.
- Instance method reference of a particular object: They refer to the instance methods of a particular object. For example, in above code
System.out::println
.
- Instance method reference of an arbitrary object: They refer to the instance methods where the first parameter is the target of the method. For example,
String::length
.
- Constructor reference: They refer to the constructor of a class. For example,
ClassName::new
.
Let’s take a deeper look at the four kinds of method references with more elaborated examples.
1. Static method references:
Static method references can be used when the method to be invoked is a static
method. For example:
package org.kodejava.basic;
import java.util.stream.Stream;
public class StaticMethodRef {
public static void main(String[] args) {
String[] array = {"Java", "Python", "Ruby", "JavaScript"};
Stream.of(array).forEach(StaticMethodRef::printStr);
}
static void printStr(String str) {
System.out.println("printStr method called with value: " + str);
}
}
In this example, the printStr
method is a static
method, and we reference this method using StaticMethodRef::printStr
.
2. Instance method reference of a particular object:
Instance method references can be used when the method to be invoked is an instance method. For example:
package org.kodejava.basic;
import java.util.stream.Stream;
public class InstanceMethodRef {
public static void main(String[] args) {
InstanceMethodRef instance = new InstanceMethodRef();
String[] array = {"Java", "Python", "Ruby", "JavaScript"};
Stream.of(array).forEach(instance::printInstanceStr);
}
void printInstanceStr(String str) {
System.out.println("printInstanceStr method called with value: " + str);
}
}
In this example, printInstanceStr
is an instance method, and we create an instance of InstanceMethodRef
and refer to an instance method instance::printInstanceStr
.
3. Instance method reference of an arbitrary object:
We can do this when we have a collection of instances and want to invoke a method on them. For example:
package org.kodejava.basic;
import java.util.stream.Stream;
public class InstanceMethodReferenceArbitrary {
public static void main(String[] args) {
String[] array = {"Java", "Python", "Ruby", "JavaScript"};
Stream.of(array).map(String::toUpperCase).forEach(System.out::println);
}
}
In this example, String::toUpperCase
invokes the toUpperCase
method for every instance of the String
in the Stream
.
4. Constructor reference:
Constructor references are used for a constructor call. For example:
package org.kodejava.basic;
import java.util.stream.Stream;
class Student {
String name;
Student(String name) {
this.name = name;
}
}
public class ConstructorReference {
public static void main(String[] args) {
Stream.of("John", "Martin", "Don")
.map(Student::new)
.forEach(student -> System.out.println("Student name is: " + student.name));
}
}
In the above example, Student::new
creates a new instance of Student
.