Method Reference in Java 8: Explained with Code Examples

Updated on September 20, 2024

Article Outline

Java 8 introduced many new features that simplify and improve the way we write code. In simpler terms, a method reference allows you to use a method without invoking it. It is helpful while using lambda expressions since it enhances the code’s comprehensibility. Understanding when and how to use method references can improve your Java programming skills when functional programming is required.

 

This blog post aims to explore what a method reference is in Java 8, why it is helpful, and the various types that exist. Each type will be explained in practical terms and examples provided so that one can learn how to apply such in real-world projects.

Prerequisites to Understand Method Reference in Java 8

To fully grasp the concept of method references, it’s essential to understand some foundational concepts in Java: methods, functional interfaces, and lambda expressions. These are key components that form the basis for method references. Let’s explore each concept.

Methods in Java

A method is a block of code that when executed, a specific task is performed. Methods can return a value or be void (no return). They can take parameters or be parameterless. In Java, methods are defined within classes and are called using objects or class names.

 

Example:

public class MathUtils { public int add(int a, int b) { return a + b; } }

Method references allow us to use a currently existing method just as an argument to the function.

Functional Interface

When we have only one abstract method in the interface then it is the functional interface. This type of interface can represent a single task or function. We can see different in-built functional interfaces which are provided by Java 8. For example, functional interfaces like Runnable, Callable, Comparator, and more. Also with the help of using the @FunctionalInterface annotation, we can create our own functional interface.

 

Example:

@FunctionalInterface interface MathOperation { int operation(int a, int b); }

Method references work seamlessly with functional interfaces. When a lambda expression implements a functional interface, a method reference can be used instead of the lambda to provide a more straightforward, readable implementation.

Lambda Expressions

Lambda expressions are anonymous functions that provide a clear and concise way to represent single-method interfaces (functional interfaces). They simplify writing small, quick functions and are often used to pass behaviour as an argument to higher-order functions.

 

Example:

 

MathOperation addition = (a, b) -> a + b;

System.out.println(“Result: ” + addition.operation(5, 3)); // Output: Result: 8

 

Lambda expressions can often be replaced by method references, making code even more compact. For example, you can use a method reference to achieve the same result when a lambda calls a method directly.

Understanding the Relationship

To use method references effectively, you need to understand the method and learn how functional interfaces and lambda expressions work together. Method references are just shorthand for lambda expressions that call existing methods. This reference points to a method by its name instead of defining a function inline, leading to more readable code. Here’s how they relate:

 

  • Methods provide reusable code blocks.
  • Functional Interfaces define the single method.
  • Lambda Expressions and Method References are ways to implement the method defined in a functional interface.

 

By understanding these relationships, you are prepared to apply method references in Java 8 correctly. Let’s dive directly into understanding the distinct varieties of method references and the way to use them in your code.

*Image
Get curriculum highlights, career paths, industry insights and accelerate your technology journey.
Download brochure

What is a Method Reference in Java 8?

A method reference in Java 8 is a shorthand notation of a lambda expression to call a method. Method references employ the symbol ‘::’ in order to distinguish the method name itself from its owner class or any other object. Such references can be made to static methods or instance methods including constructors.

Syntax of Method Reference

The syntax for method reference depends on the type of method being referred to. The general form of method reference looks like this:

 

Reference to a Static Method:

 

ClassName::staticMethodName

Example of Method Reference

Let’s see an easy example that shows how method references work. Suppose you’ve got a list of strings and you want to sort them using the compareToIgnoreCase method of the String class:

 

Using Lambda Expression:

List<String> names = Arrays.asList(“John”, “Alice”, “Bob”);

Collections.sort(names, (s1, s2) -> s1.compareToIgnoreCase(s2));

 

Using Method Reference:

List<String> names = Arrays.asList(“John”, “Alice”, “Bob”);

Collections.sort(names, String::compareToIgnoreCase);

 

Here, in this lambda expression (s1, s2)->s1.compareTolgnoreCase(s2), we can use the method reference, which is String::compareTolgnoreCase. Thus, replacing it makes the code more readable and precise.

Types of Method Reference in Java 8

Method references in Java 8 can be classified into four main types:

 

  • Method reference to an instance method of a particular object of a class
  • Static method reference
  • Method reference to an instance method of an arbitrary object of a specific type
  • Method reference to a constructor

 

Now, let’s explore each type with detailed explanations and examples.

 

Also Read: Garbage Collection in Java

Method reference to an instance method of a particular object of a class

This method references are typically used when you need to call an instance method of any specific object. This will allow you to use a reference to an existing object. It calls one of its methods directly instead of writing the whole lambda expression. The main benefit of this is it will simplify the code through directly referencing the instead method.

 

Syntax

 

The syntax for referencing an instance method of a particular object is:

 

objectName::instanceMethodName

 

  • objectName is the reference to the existing object whose method you want to refer to.
  • instanceMethodName is the name of the method that belongs to the object.

 

Example 1: Method Reference to an Instance Method of a Particular Object

 

Suppose you have a Printer class with an instance method printMessage(). You want to use this method with a lambda expression. Instead of writing a lambda, you can use a method reference.

 

Example:

import java.util.function.Consumer;   public class Printer { public void printMessage(String message) { System.out.println("Printing: " + message); }   public static void main(String[] args) { Printer printer = new Printer(); // Create an instance of Printer   // Using method reference to an instance method of a particular object Consumer<String> messagePrinter = printer::printMessage;   // Executing the method reference messagePrinter.accept("Hello, World!"); // Output: Printing: Hello, World! } }

Explanation:

 

  • Here, we have a Printer class with an instance method printMessage(String message).
  • We create an object printer of the Printer class.
  • We use a method reference printer::printMessage to refer to the printMessage method of the printer object.
  • The Consumer<String> functional interface is used to accept a single input argument and perform an operation.
  • accept(“Hello, World!”) calls the printMessage method, displaying “Printing: Hello, World!”.

 

Example 2: Using Method Reference with List forEach

 

Let’s see another example where we use method references with the forEach method of a list.

 

Example:

import java.util.Arrays; import java.util.List;  public class Printer { public void display(String item) { System.out.println("Item: " + item); }  public static void main(String[] args) { Printer printer = new Printer(); // Create an instance of Printer  List<String> items = Arrays.asList("Apple", "Banana", "Orange");  // Using method reference to an instance method of a particular object items.forEach(printer::display); // Output: Item: Apple, Item: Banana, Item: Orange } }

Explanation:

 

  • In this example, we have a method display(String item) in the Printer class that prints an item.
  • We create an instance printer of the Printer class.
  • A list items contains some strings (“Apple”, “Banana”, “Orange”).
  • The forEach method of the list is used to iterate over each item, and the method reference printer::display is passed to forEach.
  • The method reference is used to print each item in the list.

 

By using a method reference, we avoid writing a lambda expression like (item) -> printer.display(item), making the code shorter and more readable.

Static Method Reference

Static methods belong to the class itself rather than to any specific object. When you need to use a static method in a lambda expression, you can use this type of method reference to simplify the code.   Here, we do not need an instance of the class to call a static method. We can simply use static method reference directly to refer to the static method in any class.

 

Syntax

 

The syntax for referencing a static method is: ClassName::staticMethodName

  • ClassName is the name of the class that contains the static method.
  • staticMethodName is the name of the static method you want to refer to.

 

Example 1: Static method Reference for Mathematical Calculations

Here, we can create an example in which we will be using a static method reference to do a simple mathematical calculation.

Example:

import java.util.function.BiFunction;   public class Calculator { public static int add(int a, int b) { return a + b; }   public static void main(String[] args) { // Using static method reference BiFunction<Integer, Integer, Integer> addition = Calculator::add;   // Executing the method reference int result = addition.apply(5, 3); System.out.println("Result: " + result); // Output: Result: 8 } }

Explanation:

 

  • The Calculator class has a static method add(int a, int b) that returns the sum of two integers.
  • We use a static method reference Calculator::add to refer to the static add method.
  • The BiFunction functional interface takes two input arguments and produces a result.
  • The addition.apply(5, 3) method call invokes the add method, resulting in “Result: 8”.

Example 2: Static Method Reference for Utility Operations

Consider another example where we use a static method reference for a utility operation, such as converting a string to an integer.

 

Example:

import java.util.function.Function;  public class StringUtils { public static int toInteger(String s) { return Integer.parseInt(s); }  public static void main(String[] args) { // Using static method reference Function<String, Integer> stringToInteger = StringUtils::toInteger;  // Executing the method reference int number = stringToInteger.apply("123"); System.out.println("Converted Number: " + number); // Output: Converted Number: 123 } }

Explanation:

 

  • The StringUtils class has a static method toInteger(String s) that converts a string to an integer using Integer.parseInt.
  • We use a static method reference StringUtils::toInteger to refer to the static toInteger method.
  • The Function functional interface takes one input argument and produces a result.
  • The stringToInteger.apply(“123”) method call invokes the toInteger() method, resulting in “Converted Number: 123”.

Method reference to an instance method of an arbitrary object of a specific type

You must use this type of method when you have a collection of objects and you don’t know the specific instances in advance but want to apply an instance method to each object. Moreover, it can act as an even more powerful tool while working with collections and streams because it can work with instance methods of any object of a specific type.

 

Syntax

 

The syntax for referencing an instance method of an arbitrary object is: ClassName::instanceMethodName

  • ClassName is the name of the class whose method you want to refer to.
  • instanceMethodName is the name of the instance method.

 

Example 1: Method Reference with Stream for Data Manipulation

Let’s look at an example where we use a method reference to manipulate a stream of strings.

 

Example:

import java.util.Arrays; import java.util.List;  public class Example { public static void main(String[] args) { List<String> names = Arrays.asList("John", "Alice", "Bob", "Steve");  // Using method reference to an instance method of an arbitrary object of a specific type names.stream().map(String::toUpperCase).forEach(System.out::println); // Output: JOHN, ALICE, BOB, STEVE } }

Explanation:

 

  • In this example, we have a list of names.
  • And, to convert each name to uppercase, we have the map method of the Stream interface that applies the String::toUpperCase method reference to each element in the list.
  • The forEach(System.out::println) method reference prints each uppercase name to the console.

 

Example 2: Sorting a List with Method Reference

 

Now, let’s use this type of method reference to sort a list of strings in a case-insensitive manner.

 

Example:

import java.util.Arrays; import java.util.List;  public class Example { public static void main(String[] args) { List<String> names = Arrays.asList("John", "alice", "Bob", "steve");  // Using method reference to an instance method of an arbitrary object of a specific type names.sort(String::compareToIgnoreCase); names.forEach(System.out::println); // Output: alice, Bob, John, steve } }

Explanation:

 

  • We have a list of names with varying cases.
  • The sort method sorts the list using the String::compareToIgnoreCase method reference.
  • The compareToIgnoreCase method is applied to each pair of strings in the list, ensuring a case-insensitive sort.
  • Finally, the sorted names are printed using forEach(System.out::println).

Method Reference to a Constructor

A method reference to a constructor is used when you want to refer to a constructor to create new instances. It provides a more compact way to create objects compared to explicitly using the new keyword in a lambda expression. This type of method reference is handy when you need to instantiate objects within a stream or in any scenario where objects are created dynamically.

 

Syntax

 

The syntax for referencing a constructor is: ClassName::new

  • ClassName is the name of the class whose constructor you want to refer to.
  • new is the keyword used to reference the constructor.

 

Example 1: Using Constructor Reference with Supplier

 

Suppose you have a Person class, and you want to create new instances of this class using a constructor reference.

 

Example:

import java.util.function.Supplier;

class Person { private String name;   public Person() { this.name = "Unknown"; }   public String getName() { return name; } }   public class Example { public static void main(String[] args) { // Using constructor reference to create a new Person instance Supplier<Person> personSupplier = Person::new; Person person = personSupplier.get();   System.out.println("Person Name: " + person.getName()); // Output: Person Name: Unknown } }

Explanation:

 

  • The Person class has a no-argument constructor that initialises the name field to “Unknown”.
  • The Supplier<Person> interface is a functional interface that supplies new Person objects.
  • We use the constructor reference Person::new to refer to the Person constructor.
  • The personSupplier.get() method call creates a new Person instance, and “Person Name: Unknown” is printed.

 

Example 2: Using Constructor Reference with List and Stream

 

Let’s create an example where we use a constructor reference to create a list of objects.

 

Example:

import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; class Car { private String model; public Car(String model) { this.model = model; } public String getModel() { return model; } } public class Example { public static void main(String[] args) { // Using constructor reference to create a list of Car objects List<Car> cars = Stream.of("Tesla", "BMW", "Audi") .map(Car::new) .collect(Collectors.toList()) cars.forEach(car -> System.out.println("Car Model: " + car.getModel())); // Output: Car Model: Tesla, Car Model: BMW, Car Model: Audi } }

Explanation:

 

  • The Car class has a constructor that takes a string argument (model).
  • We use the Stream.of method to create a stream of car models.
  • The map(Car::new) method reference uses the constructor reference to create a new Car object for each model in the stream.
  • The collect(Collectors.toList()) method collects the new Car objects into a list.
  • Finally, each car’s model is printed using a lambda expression in forEach.

Why is Method Reference Important?

Method references are important in Java 8 for several reasons:

 

  1. Improves Code Readability: The use of method references improves the readability of the code as it avoids the complexity of coding and sources of diagrams. It helps build slanging methods rather than creating tiny margins.
  2. Reduces Code Size: Rather than writing a lambda expression, you can avoid doing so and employ a method reference which is shorter, and easier. This helps in saving the text length of your code and helps in better understanding.
  3. Supports Functional Programming: Method references align with the functional programming style introduced in Java 8. They allow you to pass behaviour (methods) as parameters, which is a core concept in functional programming.
  4. Optimised Performance: Method references can be optimised by the Java compiler, which might lead to better performance. They also provide a more natural way to use functional interfaces.
  5. Promotes Reusability: Method references provide a way to reuse existing methods and, thus prevent rewriting new code for operations that are already defined somewhere.

Conclusion

In conclusion, method references in Java 8 are a great way of enhancing the code and making it easier to read and maintain. With method references, you will replace the need to use lambda expressions wherever a method reference can be used to call a shorter code.

 

It’s always good to know what types of method references are available so that you can select the one that best fits the application task and helps improve the functionality of the Java applications you create.

 

This way of implementing method references encourages more of the functional programming approach that came with the changes in Java 8. Whatever the situation, whether it is static methods, instance methods or constructors, there is a method reference that is effective and straightforward in the expression of code.

FAQs
A shorthand notation to call methods by referring to them, instead of using lambda expressions.
Four: instance method of a particular object, static method, instance method of an arbitrary object, and constructor.
They make code more concise, readable, and maintainable, reducing boilerplate code.
No, method references can only replace lambdas that directly call an existing method.
Performance is similar; method references mainly offer code readability and simplicity.
ClassName::staticMethodName
Yes, as long as the method signature matches the abstract method of the functional interface.

Updated on September 20, 2024

Link
left dot patternright dot pattern

Programs tailored for your success

Popular

IIT Courses

Management

Data Science

Finance

Technology

Future Tech

Upskill with expert articles

View all
Hero Vired logo
Hero Vired is a leading LearnTech company dedicated to offering cutting-edge programs in collaboration with top-tier global institutions. As part of the esteemed Hero Group, we are committed to revolutionizing the skill development landscape in India. Our programs, delivered by industry experts, are designed to empower professionals and students with the skills they need to thrive in today’s competitive job market.
Blogs
Reviews
Events
In the News
About Us
Contact us
Learning Hub
18003093939     ·     hello@herovired.com     ·    Whatsapp
Privacy policy and Terms of use

|

Sitemap

© 2024 Hero Vired. All rights reserved