Java Method Reference

Java Method Reference

  • A method reference is shorthand to create a lambda expression using an existing method.
  • Using method references makes your lambda expressions more readable and concise.
  • If a lambda expression contains a body that is an expression using a method call, you can use a method reference in place of that lambda expression.
  • For instance you want to print the event object whenever a button is clicked – you could of course with lambda write:
    button.setOnAction(event -> System.out.println(event));
    
  • It would be nicer if you could just pass the println method to the setOnAction method:
    button.setOnAction(System.out::println);
    
  • The expression System.out::println is a method reference that is equivalent to the lambda expression x -> System.out.println(x).
  • The :: operator separates the method name from the name of an object or class.
  • Types of Method References:
    Syntax Description
    TypeName::staticMethod A method reference to a static method of a class, an interface, or an enum
    objectRef::instanceMethod A method reference to an instance method of the specified object
    ClassName::instanceMethod A method reference to an instance method of an arbitrary object of the specified class
    TypeName.super::instanceMethod A method reference to an instance method of the supertype of a particular object
    ClassName::new A constructor reference to the constructor of the specified class
    ArrayTypeName::new An array constructor reference to the constructor of the specified array type

TypeName::staticMethod

  • In this case we need a static method that can be executed through the class name :
    public class Calculator {
    
      // static method and owned bye the class
      public static int mul(int a, int b) {
        return a * b;
      }
    
      public static void main(String[] args) {
        // Using a lambda expression
        IntBinaryOperator operator1 = (a, b) -> Calculator.mul(a, b);
        System.out.println(operator1.applyAsInt(5, 6));
    
        // Using a method reference
        IntBinaryOperator operator2 = Calculator::mul;
        System.out.println(operator2.applyAsInt(5, 6));
    
      }
    }
    
    The result of this is:
    30
    30
    You can download this example here (needed tools can be found in the right menu on this page).

objectRef::instanceMethod and ClassName::instanceMethod

  • The object reference on which an instance method is invoked is known as the receiver of the method invocation.
  • You can specify the receiver of the method invocation: provide it implicitly when the method is invoked.
    1. Explicitly, which is known as a bound receiver.
    2. provide it implicitly when the method is invoked, which is known as unbound receiver

    Bound receiver

    For a bound receiver, use the objectRef::instanceMethod syntax.
    public class BoundType {
    
      // instance method 
      public int cubic(int a) {
        return a * a * a;
      }
    
      public static void main(String[] args) {
        BoundType cal = new BoundType();
        // Using a lambda expression
        Function<Integer, Integer> operator3 = (a) -> cal.cubic(a);
        System.out.println(operator3.apply(6));
    
        // Using a method reference (bound type)
        Function<Integer, Integer> operator4 = cal::cubic;
        System.out.println(operator4.apply(6));
    
      }
    }
    
    The result of this is:
    216
    216
    You can download this example here (needed tools can be found in the right menu on this page).

    UnBound receiver

    For an unbound receiver, use the ClassName::instanceMethod syntax.
    public class UnBoundType {
    
      // instance method 
      public int cubic(int a) {
        return a * a * a;
      }
    
      public static void main(String[] args) {
        UnBoundType cal = new UnBoundType();
    
        // Using a lambda expression
        BiFunction<UnBoundType, Integer, Integer> operator1 = (a, b) -> a.cubic(b);
        System.out.println(operator1.apply(cal, 6));
    
        // Using a method reference (UnBound type)
        BiFunction<UnBoundType, Integer, Integer> operator2 = UnBoundType::cubic;
        System.out.println(operator2.apply(cal, 6));
      }
    }
    
    The result of this is:
    216
    216
    You can download this example here (needed tools can be found in the right menu on this page).

TypeName.super::instanceMethod

  • The keyword super is used as a qualifier to invoke the overridden method in a class or an interface.
  • The keyword is available only in an instance context.
    interface Defaults {
      default int doMath(int a) {
        return 2 * a;
      }
    }
    public class Calculator implements Defaults {
    
      // static method and owned bye the class
      @Override
      public int doMath(int a) {
        return a * a;
      }
    
      public void test(int value) {
        // Uses Calculator.doMath() method
        Function<Integer, Integer> operator1 = this::doMath;
        System.out.println("this::doMath(): " +operator1.apply(value));
        // Uses Defaults.doMath() method
        Function<Integer, Integer> operator2 = Defaults.super::doMath;
        System.out.println("Defaults::doMath(): " +operator2.apply(value));
      }
    
      public static void main(String[] args) {
        Calculator cal = new Calculator();
        cal.test(7);
      }
    }
    
    
    The result of this is:
    this::doMath(): 49
    Defaults::doMath(): 14
    You can download this example here (needed tools can be found in the right menu on this page).

ClassName::new

  • Constructor references are just like method references, except that the name of the method is new.
  • For example, Button::new is a reference to a Button constructor.
  • The context determines which button constructors to be used as there are several such to choose between.
    List<String> labels = ...;
    Stream<Button> stream = labels.stream().map(Button::new);
    List<Button> buttons = stream.collect(Collectors.toList());
    
  • The compiler picks the one with a String parameter because it infers from the context that the constructor is called with a string.
  • You can form constructor references with array types.
    int[] :: new;     // the parameter is length of the array.
    x -> new int[x];  // This is the equivalent lambda expression  
    
  • Here is two constructor references example:
    public class Timer {
    
      public void oper(Supplier<GregorianCalendar> supplier) {
        System.out.println(supplier.get().getTime());
      }
    
      public static void main(String[] args) {
    
        Timer timer = new Timer();
        // Referencing the constructor
        // Using a lambda expression
        timer.oper(() -> new GregorianCalendar());  
        // Using a constructor reference
        timer.oper(GregorianCalendar::new); 
      }
    }
    

    interface ArrayCreator {
      int[] MakeArray(int noOfEle);
    }
    
    public class ArrayNew {
    
      public static void main(String[] args) {
    
        ArrayCreator arrayCreator = int[]::new;
        int[] intArr = arrayCreator.MakeArray(10);
        for (int i = 0; i < intArr.length; i++) {
          intArr[i] = i * i - i / 2;
          System.out.println("[" + i + "] = " + intArr[i]);
        }
      }
    }
    
    The result of this is:
    Wed Apr 27 11:29:09 CEST 2016
    Wed Apr 27 11:29:09 CEST 2016
    and
    [0] = 0
    [1] = 1
    [2] = 3
    [3] = 8
    [4] = 14
    [5] = 23
    [6] = 33
    [7] = 46
    [8] = 60
    [9] = 77
    You can download these examples here (needed tools can be found in the right menu on this page).
© 2010 by Finnesand Data. All rights reserved.
This site aims to provide FREE programming training and technics.
Finnesand Data as site owner gives no warranty for the correctness in the pages or source codes.
The risk of using this web-site pages or any program codes from this website is entirely at the individual user.