Method References in Java 8
- Method references are shorthand notations for lambda expressions that directly call a method or constructors using the
::operator. - Method references provide a way to refer to a method without executing it. Instead of creating a lambda expression to perform a specific operation, developers can reference an existing method to perform the same operation.
- Method references provide a concise syntax for invoking a method, and they can be used in place of lambda expressions in certain cases.

Difference Between Lambda Expression and Method Reference
- Use lambda expressions when you need to implement behavior that isn’t directly tied to a method.
- Use method references when you can directly refer to existing methods for a clearer and more concise syntax.
- Lambda Expression: More flexible; can include custom logic.
- Method Reference: Less flexible; limited to existing methods.
In Java, there are four types of method references:
- A method reference to a static method
Syntax: ClassName::staticMethodName Example: Math::max
2. A method reference to an instance method of an object of a particular type
Syntax: instance::methodName Example: System.out::println
3. A method reference to an instance method of an existing object
Syntax: ClassName::instanceMethodName
Example: String::toLowerCase4. A method reference to a constructor
Syntax: ClassName::new
Example: ArrayList::newFor each type of Method reference, I have discussed two examples. After finishing, you will be able to understand method reference deeply. Please giving it claps👏 if this article is useful.
Functional interface knowledge is required to read this article. Please refer my article for functional interface.
1. Reference to a Static Method
Example 1: Basic usage of method reference to a static method
import java.util.Arrays;
import java.util.List;
public class StaticMethodReferenceExample {
// Static method
public static void printMessage(String message) {
System.out.println(message);
}
public static void main(String[] args) {
List<String> messages = Arrays.asList("Hello", "World", "Java 8");
// Using method reference to a static method
messages.forEach(StaticMethodReferenceExample::printMessage);
}
}Example 2: Method reference with built-in static method (e.g., Integer::parseInt)
import java.util.function.Function;
import java.util.Arrays;
import java.util.List;
public class StaticMethodReferenceWithBuiltInMethod {
public static void main(String[] args) {
List<String> numbers = Arrays.asList("1", "2", "3", "4");
// Using method reference for built-in static method Integer::parseInt
Function<String, Integer> parseIntFunction = Integer::parseInt;
numbers.stream()
.map(parseIntFunction) // Converts each string to an integer
.forEach(System.out::println); // Prints each integer
}
}2. Reference to an Instance Method Example 1 :
import java.util.function.Function;
public class MethodReferenceExample {
public String convertToUpperCase(String input) {
return input.toUpperCase();
}
public static void main(String[] args) {
// Creating an instance of the class
MethodReferenceExample example = new MethodReferenceExample();
// Using lambda expression
Function<String, String> lambdaFunction = s -> example.convertToUpperCase(s);
// Using method reference
Function<String, String> methodRefFunction = example::convertToUpperCase;
// Test the method reference
String result = methodRefFunction.apply("hello");
System.out.println(result); // Output: HELLO
}
}example::convertToUpperCaseis the method reference to the instance methodconvertToUpperCaseof theexampleobject.- This is more concise than using a lambda like
s -> example.convertToUpperCase(s).
Example 2 : Reference to an Instance Method in a Collection
import java.util.Arrays;
import java.util.List;
public class InstanceMethodReferenceExample {
public void printMessage(String message) {
System.out.println(message);
}
public static void main(String[] args) {
// Create an instance of the class
InstanceMethodReferenceExample example = new InstanceMethodReferenceExample();
// Create a list of strings
List<String> messages = Arrays.asList("Hello", "World", "Java", "Method Reference");
// Using lambda expression to print each message
messages.forEach(msg -> example.printMessage(msg));
// Using method reference to an instance method of a particular object
messages.forEach(example::printMessage);
}
}3. A method reference to an instance method of an existing object A reference to an instance method of an arbitrary object of a particular type in Java 8 refers to cases where you call an instance method on an object of a specific type, but the object is not explicitly defined when the method reference is made.
This is commonly used in stream operations, where you can apply a method on elements of a collection. The syntax for this method reference is ClassName::methodName.
Example 1 :
import java.util.Arrays;
import java.util.List;
public class InstanceMethodReferenceExample {
public static void main(String[] args) {
// Create a list of strings
List<String> messages = Arrays.asList("hello", "world", "java", "method reference");
// Using lambda expression to convert each string to uppercase
messages.stream()
.map(s -> s.toUpperCase()) // lambda version
.forEach(System.out::println);
// Using method reference to an instance method of an arbitrary object
messages.stream()
.map(String::toUpperCase) // method reference version
.forEach(System.out::println);
}
}
// OUTPUT
HELLO
WORLD
JAVA
METHOD REFERENCEExplanation:
String::toUpperCaseis a reference to thetoUpperCaseinstance method of theStringclass.- Here, we are not specifying which particular
Stringobject to use when defining the method reference. Instead, the method reference will be applied to each element in the stream (which areStringobjects). - The method reference
String::toUpperCaseapplies thetoUpperCasemethod on eachStringin themessageslist during the stream operation.
Example 2 : Reference to an Instance Method of an Arbitrary Object of a Particular Type
import java.util.Arrays;
import java.util.List;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class InstanceMethodReferenceExample {
public static void main(String[] args) {
// Creating a list of Person objects
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// Using lambda expression to get names
people.stream()
.map(person -> person.getName()) // lambda version
.forEach(System.out::println);
// Using method reference to an instance method of an arbitrary object
people.stream()
.map(Person::getName) // method reference version
.forEach(System.out::println);
}
}
// OUTPUT
Alice
Bob
CharlieExplanation:
Person::getNameis a reference to thegetNameinstance method of thePersonclass.- The method reference applies the
getName()method on eachPersonobject in the list, retrieving the name for each person. - This is more concise than using the lambda expression
person -> person.getName().
4. Reference to a Constructor
In Java 8, constructor references allow you to refer to constructors using the ClassName::new syntax. Constructor references are particularly useful when working with functional interfaces like Supplier, Function, and BiFunction. They provide a concise way to create new objects.
Example 1: Constructor Reference with No Arguments
In this example, we’ll create a simple class Person with a no-argument constructor and use a constructor reference to create a new Person object.
import java.util.function.Supplier;
class Person {
private String name;
public Person() {
this.name = "Unknown";
}
public String getName() {
return name;
}
}
public class ConstructorReferenceExample1 {
public static void main(String[] args) {
// Using lambda expression to create a new Person
Supplier<Person> personSupplierLambda = () -> new Person();
Person person1 = personSupplierLambda.get();
System.out.println("Person 1 Name: " + person1.getName()); // Output: Person 1 Name: Unknown
// Using constructor reference to create a new Person
Supplier<Person> personSupplierRef = Person::new;
Person person2 = personSupplierRef.get();
System.out.println("Person 2 Name: " + person2.getName()); // Output: Person 2 Name: Unknown
}
}
//Output
Person 1 Name: Unknown
Person 2 Name: UnknownExplanation:
Supplier<Person>is a functional interface that supplies aPersonobject.- The lambda expression
() -> new Person()creates a newPersonusing the no-argument constructor. - The constructor reference
Person::newis a concise way to reference thePersonconstructor without arguments. - Both the lambda and constructor reference versions create a
Personwith the default name"Unknown".
Example 2: Constructor Reference with Arguments
In this example, we’ll modify the Person class to include a constructor that accepts arguments and use a constructor reference with the Function interface to create new Person objects.
import java.util.function.Function;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class ConstructorReferenceExample2 {
public static void main(String[] args) {
// Using lambda expression to create a new Person with name and age
Function<String, Person> personFunctionLambda = (name) -> new Person(name, 25);
Person person1 = personFunctionLambda.apply("Alice");
System.out.println("Person 1: " + person1.getName() + ", Age: " + person1.getAge()); // Output: Alice, Age: 25
// Using constructor reference to create a new Person
Function<String, Person> personFunctionRef = name -> new Person(name, 25);
Person person2 = personFunctionRef.apply("Bob");
System.out.println("Person 2: " + person2.getName() + ", Age: " + person2.getAge()); // Output: Bob, Age: 25
}
}
//Output
Person 1: Alice, Age: 25
Person 2: Bob, Age: 25Explanation:
Function<String, Person>is a functional interface that takes aString(name) and returns aPersonobject.- The lambda expression
(name) -> new Person(name, 25)creates a newPersonwith a specified name and age25. - The constructor reference
Person::new(for an overloaded constructor with parameters) is a concise way to create a newPersonobject with the provided name, but in this case, the constructor requires two arguments (nameandage), so we need to specify age directly in the lambda.
👏 If you found my articles useful, please consider giving it claps and sharing it with your friends and colleagues.
To read other topics
- ExecutorService, Thread Pools, Future Interface, Runnable, and Callable
- Spring Boot Circuit Breaker Example with Resilience4j: Step-by-Step Guide
- Spring Boot Retry Pattern Example with Resilience4j: Step-by-Step Guide
- Mastering Transaction Propagation and Isolation in Spring Boot
- @Formula Annotation in Spring Boot
- Understanding Logging in Spring Boot: A Complete Overview with Example
- Understanding Hash Collisions in Java’s HashMap
- Exploring Java Collections: A Guide to Lists, Sets, Queues, and Maps
- Using the @Temporal Annotation in Hibernate and Spring Boot
- Understanding CORS and CSRF in Spring Boot
- Complete CRUD Example in Spring Boot with DTO Validation, and Common API Response using MySQL
- Guide to Spring Boot Validation Annotations
- Mastering Git and GitHub Integration in IntelliJ IDEA
- Spring Boot Profiles
- Design Pattern in java
