How to Pass a Method as a Parameter in Java

Mohammad Irfan Feb 02, 2024
  1. Pass a Method as a Parameter by Using the lambda Function in Java
  2. Pass a Method as a Parameter Using the Method Reference in Java
  3. Pass a Method as a Parameter in Java Using Interfaces
  4. Pass a Method as a Parameter in Java Using Java 8 Functional Interfaces
  5. Pass a Method as a Parameter in Java Using Anonymous Classes
  6. Conclusion
How to Pass a Method as a Parameter in Java

In Java, the ability to pass methods as parameters is a useful feature that enhances code flexibility and promotes a more modular and reusable design. Whether you are working with traditional interfaces, Java 8 functional interfaces, lambda expressions, or method references, the language provides several approaches to achieve this functionality.

This article delves into the techniques and syntax for passing methods as parameters in Java.

Pass a Method as a Parameter by Using the lambda Function in Java

In Java, lambda expressions provide a concise way to express instances of single-method interfaces (functional interfaces). This feature is particularly useful when it comes to passing methods as parameters.

The lambda expression syntax consists of three parts:

(parameters) -> expression

Where:

  • parameters: A comma-separated list of formal parameters.
  • ->: The arrow token separating the parameters from the body of the lambda expression.
  • expression: The body of the lambda expression, which represents the method implementation.

Let’s consider a scenario where we have a functional interface, MyFunctionalInterface, with a single method, myMethod().

@FunctionalInterface
interface MyFunctionalInterface {
  void myMethod();
}

Now, let’s create a method, executeMethod, that takes an instance of this functional interface as a parameter and invokes its method.

@FunctionalInterface
interface MyFunctionalInterface {
  void myMethod();
}

public class LambdaExample {
  static void executeMethod(MyFunctionalInterface obj) {
    obj.myMethod();
  }

  public static void main(String[] args) {
    executeMethod(() -> System.out.println("Executing myMethod"));
  }
}

In the code above, we define a functional interface, MyFunctionalInterface, using the @FunctionalInterface annotation. This interface has a single abstract method, myMethod().

The executeMethod method takes an instance of this interface as a parameter and calls its myMethod().

In the main method, we use a lambda expression to pass a method as a parameter to executeMethod. The lambda expression () -> System.out.println("Executing myMethod") represents the implementation of the myMethod in the functional interface.

It’s a concise way of defining the behavior of the method without explicitly creating a separate class or using an anonymous class.

Output:

Executing myMethod

This output confirms that the lambda expression successfully passed the method as a parameter, and the myMethod implementation was executed within the executeMethod method.

Now, let’s further explore the concept of passing methods as parameters using lambda expressions with another example. In this case, we’ll work with a functional interface called Doable, which has a single method, doSomething(String str).

interface Doable {
  String doSomething(String str);
}

public class SimpleTesting {
  public static void main(String[] args) {
    Doable doa = (str) -> str + " Rohan";
    show("Hello", doa);
  }

  public static void show(String msg, Doable doa) {
    String greeting = doa.doSomething(msg);
    System.out.println(greeting);
  }
}

In this additional example, we define a functional interface Doable with a single method doSomething(String str). The SimpleTesting class demonstrates the usage of lambda expressions to pass methods as parameters.

In the main method, we create a lambda expression (str) -> str + " Rohan" that implements the doSomething method of the Doable interface. This lambda expression concatenates the string " Rohan" to the input string.

Next, we invoke the show method, passing the lambda expression as a parameter along with the string "Hello".

The show method, which takes a Doable instance and a message as parameters, calls the doSomething method on the provided Doable instance (doa). The result is then printed to the console.

Output:

Hello Rohan

This output demonstrates that the lambda expression (str) -> str + " Rohan" was successfully passed as a method to the show method, and its implementation was executed within the context of the Doable functional interface.

Pass a Method as a Parameter Using the Method Reference in Java

In addition to lambda expressions, Java 8 and later versions introduce method references, providing another way to pass methods as parameters. Method references offer a more concise syntax when the lambda expression simply calls an existing method.

A method reference is denoted by :: and is used to refer to a method by its name. The syntax varies depending on the type of method being referenced:

Reference to a static method:

ClassName::staticMethodName

Reference to an instance method of a particular object:

instance::instanceMethodName

Reference to an instance method of an arbitrary object of a particular type:

ClassName::instanceMethodName

Reference to a constructor:

ClassName::new

Let’s consider a scenario where we have a class MethodReferenceExample with a static method staticMethod and an instance method instanceMethod.

import java.util.function.Consumer;

public class MethodReferenceExample {
  static void staticMethod(String message) {
    System.out.println("Static method: " + message);
  }

  void instanceMethod(String message) {
    System.out.println("Instance method: " + message);
  }

  public static void main(String[] args) {
    Consumer<String> staticConsumer = MethodReferenceExample::staticMethod;
    staticConsumer.accept("Hello, Static!");

    MethodReferenceExample instance = new MethodReferenceExample();
    Consumer<String> instanceConsumer = instance::instanceMethod;
    instanceConsumer.accept("Hello, Instance!");
  }
}

In the example above, we have a class MethodReferenceExample with a static method staticMethod and an instance method instanceMethod. We demonstrate both types of method references.

In the main method, we first create a Consumer that references the static method using MethodReferenceExample::staticMethod. This reference is then passed to the accept method, which invokes the static method with the provided message.

Next, we create an instance of MethodReferenceExample and use a method reference to an instance method. The instance::instanceMethod syntax creates a Consumer that refers to the instance method.

When the accept method is called on this consumer, the instance method is invoked with the specified message.

Output:

Static method: Hello, Static!
Instance method: Hello, Instance!

This output confirms that the method references successfully passed the methods as parameters, and both the static and instance methods were executed based on the method references provided.

Pass a Method as a Parameter in Java Using Interfaces

In Java, one of the fundamental ways to pass a method as a parameter is by utilizing interfaces. By defining an interface with a single abstract method, often referred to as a functional interface, and implementing that interface with different classes or instances, we can effectively pass methods around as parameters.

Let’s start with the syntax of defining a functional interface:

interface MyFunctionalInterface {
  void myMethod();
}

Consider a scenario where we have a functional interface, MyFunctionalInterface, with a single method, myMethod.

interface MyFunctionalInterface {
  void myMethod();
}

class MyClass implements MyFunctionalInterface {
  @Override
  public void myMethod() {
    System.out.println("Executing myMethod in MyClass");
  }
}

public class InterfaceExample {
  static void executeMethod(MyFunctionalInterface obj) {
    obj.myMethod();
  }

  public static void main(String[] args) {
    MyClass myClass = new MyClass();
    executeMethod(myClass);
  }
}

In this example, we define a functional interface, MyFunctionalInterface, with a single abstract method, myMethod. The MyClass class implements this interface, providing its implementation for the myMethod method.

The InterfaceExample class contains a method named executeMethod, which takes an instance of MyFunctionalInterface as a parameter and calls its myMethod.

In the main method, we create an instance of MyClass and pass it as a parameter to the executeMethod method. Effectively, we are passing the implementation of the myMethod method through the MyFunctionalInterface interface.

Output:

Executing myMethod in MyClass

This output demonstrates that the method implementation within the MyClass instance was successfully passed as a parameter using the MyFunctionalInterface. The executeMethod method invoked the myMethod of the provided instance, resulting in the printed message.

Utilizing interfaces is especially valuable when working with existing classes or instances that implement a specific interface.

Pass a Method as a Parameter in Java Using Java 8 Functional Interfaces

In Java 8 and later versions, the introduction of functional interfaces such as Supplier, Consumer, Predicate, and Function provides a streamlined way to pass methods as parameters. These interfaces define single abstract methods, making them suitable for lambda expressions and method references.

Syntax for Functional Interfaces:

Supplier<T>: Represents a supplier of results, takes no arguments, and produces a result of type T.

Supplier<String> supplier = () -> "Hello, Supplier!";

Consumer<T>: Represents an operation that takes a single input argument of type T and returns no result.

Consumer<String> consumer = message -> System.out.println("Consumer says: " + message);

Predicate<T>: Represents a predicate (boolean-valued function) of one argument of type T.

Predicate<Integer> predicate = num -> num > 0;

Function<T, R>: Represents a function that takes one argument of type T and returns a result of type R.

Function<String, Integer> function = str -> str.length();

Let’s consider a scenario where we use these functional interfaces to pass methods as parameters.

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class FunctionalInterfaceExample {
  public static void main(String[] args) {
    Supplier<String> supplier = () -> "Hello, Supplier!";
    executeSupplier(supplier);

    Consumer<String> consumer = message -> System.out.println("Consumer says: " + message);
    executeConsumer("Hello, Consumer!", consumer);

    Predicate<Integer> predicate = num -> num > 0;
    executePredicate(5, predicate);

    Function<String, Integer> function = str -> str.length();
    executeFunction("Hello, Function!", function);
  }

  static void executeSupplier(Supplier<String> supplier) {
    System.out.println("Supplier says: " + supplier.get());
  }

  static void executeConsumer(String message, Consumer<String> consumer) {
    consumer.accept(message);
  }

  static void executePredicate(int num, Predicate<Integer> predicate) {
    System.out.println("Is " + num + " greater than 0? " + predicate.test(num));
  }

  static void executeFunction(String str, Function<String, Integer> function) {
    System.out.println("Length of the string: " + function.apply(str));
  }
}

In this example, we use four Java 8 functional interfaces to pass methods as parameters:

  1. Supplier: The executeSupplier method takes a Supplier as a parameter and executes its get method, printing the result.

  2. Consumer: The executeConsumer method takes a Consumer as a parameter and executes its accept method, passing a message.

  3. Predicate: The executePredicate method takes a Predicate as a parameter and tests it with an integer, printing the result.

  4. Function: The executeFunction method takes a Function as a parameter and applies it to a string, printing the result.

In the main method, we create instances of these functional interfaces using lambda expressions, and then we pass them as parameters to the corresponding methods.

Output:

Supplier says: Hello, Supplier!
Consumer says: Hello, Consumer!
Is 5 greater than 0? true
Length of the string: 16

This output confirms that the methods were successfully passed as parameters using Java 8 functional interfaces, and their implementations were executed within the respective methods.

Pass a Method as a Parameter in Java Using Anonymous Classes

Java also allows us to use anonymous classes to pass methods as parameters. Anonymous classes are particularly useful when working with interfaces that have a single abstract method (functional interfaces).

To use an anonymous class to implement an interface or extend a class, you can follow this syntax:

interface MyInterface {
  void myMethod();
}

MyInterface myInterface = new MyInterface() {
  @Override
  public void myMethod() {
    // Implementation of myMethod
  }
};

Consider a scenario where we have a functional interface MyFunctionalInterface with a single method myMethod.

interface MyFunctionalInterface {
  void myMethod();
}

public class AnonymousClassExample {
  static void executeMethod(MyFunctionalInterface obj) {
    obj.myMethod();
  }

  public static void main(String[] args) {
    executeMethod(new MyFunctionalInterface() {
      @Override
      public void myMethod() {
        System.out.println("Executing myMethod anonymously");
      }
    });
  }
}

In this example, we have a functional interface, MyFunctionalInterface, with a single method, myMethod. The AnonymousClassExample class contains a method, executeMethod, which takes an instance of this functional interface as a parameter and calls its myMethod.

In the main method, we use an anonymous class to provide the implementation of the myMethod. The syntax new MyFunctionalInterface() {...} creates an anonymous class that implements the MyFunctionalInterface interface.

Inside the anonymous class, we override the myMethod and specify its implementation, which prints a message to the console. The executeMethod is then called with an instance of the anonymous class as a parameter, effectively passing the method as an argument.

Output:

Executing myMethod anonymously

While lambda expressions and method references offer concise alternatives, using anonymous classes remains a valid approach to pass methods as parameters in Java, especially in scenarios involving functional interfaces.

Conclusion

Java offers several approaches to passing methods as parameters. Whether using traditional interfaces, the concise syntax of lambda expressions and method references in Java 8, or functional interfaces like Supplier, Consumer, Predicate, and Function, you have an array of tools at your disposal.

By choosing the most suitable approach based on the specific requirements of a given task, you can foster clean, modular, and maintainable code.

Related Article - Java Method