Java 8 introduces a new feature called method reference. Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when we use lambda expression for referring a method, we can replace lambda expression with method reference.
In this chapter, we will learn about Java Method References, their types (static, instance, and constructor), syntax, and how to use them with functional interfaces through practical examples.
A method reference is a shorthand notation used to call a method by referring to it directly using the :: operator. It is a compact alternative to lambda expressions when the lambda simply invokes an existing method.
In Java, there are four main types of method references introduced in Java 8:
We can refer to static method defined in the class. It is used When a lambda expression just calls a static method. Following is the syntax and example which describe the process of referring static method in Java.
Syntax:
ClassName::staticMethodName
For example,
list.forEach(Math::abs); // Equivalent to: n -> Math.abs(n)
Example
interface Sayable{
void say();
}
public class Main {
public static void saySomething() {
System.out.println("Hello, this is static method.");
}
public static void main(String[] args) {
// Referring static method
Sayable sayable = Main::saySomething;
// Calling interface method
sayable.say();
}
}
Output:
Hello, this is static method.
Example:
In the following example, we are using predefined functional interface Runnable to refer static() method.
Java
public class Main {
public static void ThreadStatus(){
System.out.println("Thread is running...");
}
public static void main(String[] args) {
Thread t2=new Thread(Main::ThreadStatus);
t2.start();
}
}
Output:
Thread is running...
Example:
We can also use predefined functional interface to refer methods. In the following example, we are using BiFunction interface and using it's apply() method.
Java
import java.util.function.BiFunction;
class Arithmetic {
public static int add(int a, int b){
return a+b;
}
}
class Main {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder = Arithmetic::add;
int result = adder.apply(10, 20);
System.out.println(result);
}
}
Output:
30
Example:
We can also override static methods by referring methods. In the following example, we have defined and overloaded three add methods.
Java
import java.util.function.BiFunction;
class Arithmetic {
public static int add(int a, int b){
return a+b;
}
public static float add(int a, float b){
return a+b;
}
public static float add(float a, float b){
return a+b;
}
}
class Main {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder1 = Arithmetic::add;
BiFunction<Integer, Float, Float>adder2 = Arithmetic::add;
BiFunction<Float, Float, Float>adder3 = Arithmetic::add;
int result1 = adder1.apply(10, 20);
float result2 = adder2.apply(10, 20.0f);
float result3 = adder3.apply(10.0f, 20.0f);
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
}
}
Output:
30 30.0 30.0
Like static methods, we can refer instance methods also. It is used when we already have an object and want to use its method.
Syntax:
instance::instanceMethodName
For example,
System.out::println; // Equivalent to: s -> System.out.println(s)
Example:
In the following example, we are referring non-static methods. We can refer methods by class object and anonymous object.
Java
interface Sayable{
void say();
}
public class Main {
public void saySomething() {
System.out.println("Hello, this is non-static method.");
}
public static void main(String[] args) {
Main methodReference = new Main(); // Creating object
// Referring non-static method using reference
Sayable sayable = methodReference::saySomething;
// Calling interface method
sayable.say();
// Referring non-static method using anonymous object
Sayable sayable2 = new Main()::saySomething; // You can use anonymous object also
// Calling interface method
sayable2.say();
}
}
Output:
Hello, this is non-static method. Hello, this is non-static method
Example:
In the following example, we are referring instance (non-static) method. Runnable interface contains only one abstract method. So, we can use it as functional interface.
Java
public class Main {
public void printnMsg(){
System.out.println("Hello, this is instance method");
}
public static void main(String[] args) {
Thread t2=new Thread(new Main()::printnMsg);
t2.start();
}
}
Output:
Hello, this is instance method
Example:
In the following example, we are using BiFunction interface. It is a predefined interface and contains a functional method apply(). Here, we are referring add method to apply method.
Java
import java.util.function.BiFunction;
class Arithmetic {
public int add(int a, int b){
return a+b;
}
}
class Main {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer>adder = new Arithmetic()::add;
int result = adder.apply(10, 20);
System.out.println(result);
}
}
Output:
30
It is used when the first parameter of the lambda provides the instance.
Syntax:
ClassName::instanceMethodName
For example,
String::toUpperCase; // Equivalent to: s -> s.toUpperCase()
Example
In the following example, String::toUpperCase is an unbound method reference. It means that for each element in the stream (a String), call its toUpperCase() method. The compiler treats it as s -> s.toUpperCase().
It works because the first parameter of the functional interface (Function<T,R>) provides the instance (s).
Java
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a list of strings
List<String> names = Arrays.asList("Jeep", "Truck", "Bus", "Car");
// Using method reference to an instance method of an arbitrary object
// String::toUpperCase means: s -> s.toUpperCase()
names.stream()
.map(String::toUpperCase) // Unbound reference
.forEach(System.out::println);
}
}
Output:
JEEP TRUCK BUS CAR
We can refer a constructor by using the new keyword. It is used when a lambda creates a new object. Here, we are referring constructor with the help of functional interface.
Syntax:
ClassName::new
For example,
Supplier<List<String>> supplier = ArrayList::new; // Equivalent to: () -> new ArrayList<String>()
Example
In this example, a constructor reference (Message::new) is used to create an object of the Message class through a functional interface in a concise and readable way.
Java
interface Messageable {
Message getMessage(String msg);
}
class Message {
Message(String msg){
System.out.print(msg);
}
}
public class Main {
public static void main(String[] args) {
Messageable hello = Message::new;
hello.getMessage("Hello");
}
}
Output:
Hello
We request you to subscribe our newsletter for upcoming updates.

We deliver comprehensive tutorials, interview question-answers, MCQs, study materials on leading programming languages and web technologies like Data Science, MEAN/MERN full stack development, Python, Java, C++, C, HTML, React, Angular, PHP and much more to support your learning and career growth.
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India