Java Lambda - Java Instance Method Reference








We can get an instance method reference in two ways, from the object instance or from the class name.

Basically we have the following two forms.

  • instance::MethodName
  • ClassName::MethodName

Here the instance represents any object instance. ClassName is the name of the class, such as String, Integer.

instance and ClassName are called the receiver. More specifically, instance is called bounded receiver while ClassName is called unbounded receiver.

We call instance bounded receiver since the receiver is bounded to the instance.

ClassName is unbouned receiver since the receiver is bounded later.





Bound Instance Method Reference

Bound Receiver receiver has the following form:

instance::MethodName

In their following code we use the buildin system functional interface Supplier as the lambda expression type.

At first we define a lambda expression in a normal way. The lambda expression accepts no parameter and returns the length of a string 'java2s.com'

Then we create a String instance with 'java2s.com' and use its length method as the instance method reference.

Bound means we already specify the instance.

The following example shows how to use bound receiver and method with no parameters to create Instance Method References.

import java.util.function.Supplier;
//  ww w. j  a  v  a 2  s  .  c om
public class Main{
  public static void main(String[] argv){
    Supplier<Integer> supplier  = () ->  "java2s.com".length(); 
    System.out.println(supplier.get());
    
    
    Supplier<Integer> supplier1  = "java2s.com"::length; 
    System.out.println(supplier1.get());
  }
}

The code above generates the following result.





Example 1

The following example shows how to use bound receiver and method with parameters to create Instance Method References.

import java.util.function.Consumer;
/*ww  w.ja v a2 s.  c  om*/
public class Main{
  public static void main(String[] argv){
    Util util = new Util();
    
    Consumer<String> consumer  = str ->  util.print(str);
    consumer.accept("Hello"); 
    

    Consumer<String> consumer1  = util::print;
    consumer1.accept("java2s.com");
    
    util.debug();
  }
}
class Util{
  private int count=0;
  public void print(String s){
    System.out.println(s);
    count++;
  }
  public void debug(){
    System.out.println("count:" + count);
  }
}

The code above generates the following result.

Unbound Instance Method Reference

An unbound receiver uses the following syntax

ClassName::instanceMethod

It is the same syntax we use to reference a static method.

From the following code we can see that the input type is the type of ClassName.

In the following code we use String:length so the functional interface input type is String.

The lambda expression gets the input when it is being used.

The following code uses the String length method as unbind instance method reference.

The String length method is usually called on a string value instance and returns the length of the string instance. Therefore the input is the String type and output is the int type, which is matching the buildin Function functional interface.

Each time we call strLengthFunc we pass in a string value and the length method is called from the passed in string value.

import java.util.function.Function;
//from w w w  . ja v  a 2 s.  c  o  m
public class Main{
  public static void main(String[] argv){
    Function<String,  Integer> strLengthFunc = String::length; 
    String name ="java2s.com";
    int len   =  strLengthFunc.apply(name); 
    System.out.println("name  = "  +  name + ", length = "  + len);
    
    name ="www.java2s.com";
    len   =  strLengthFunc.apply(name); 
    System.out.println("name  = "  +  name + ", length = "  + len);

  }
}

The code above generates the following result.

Example 2

The following code defines a class Util with a static method called append.

The append method accepts two String type parameters and returns a String type result.

Then the append method is used to create a lambda expression and assigned to Java buildin BiFunction functional interface.

The signature of append method matches the signature of the abstract method defined in BiFunction functional interface.

import java.util.function.BiFunction;
/*from  w  w  w  . j a  v  a 2s  .c  om*/
public class Main{
  public static void main(String[] argv){
    BiFunction<String,  String,String> strFunc = Util::append; 
    String name ="java2s.com";
    String s=  strFunc.apply(name,"hi"); 
    System.out.println(s);
  }
}
class Util{
  public static String append(String s1,String s2){
    return s1+s2;
  }  
}

The code above generates the following result.

Supertype Instance Method References

The keyword super, which is only used in an instance context, references the overridden method.

We can use the following syntax to create a method reference that refers to the instance method in the parent type.

ClassName.super::instanceMethod

The following code defines a parent class called ParentUtil. In ParentUtil there is a method named append which appends two String value together.

Then a child class called Util is created and extending the ParentUtil.

Inside Util class the append method is overrided.

In the constructor of Util we create two lambda expression, one is by using the append method from Util, the other is using the append method from ParentUtil class.

We use this::append to reference the current class while using Util.super::append to reference the method from parent class.

import java.util.function.BiFunction;
//from   w  w w.jav a  2  s . c  o  m
public class Main{
  public static void main(String[] argv){
    new Util();
  }
}
class Util extends ParentUtil{
  
  public Util(){
    BiFunction<String,  String,String> strFunc = this::append; 
    String name ="java2s.com";
    String s=  strFunc.apply(name," hi"); 
    System.out.println(s);
    
    strFunc = Util.super::append; 
    name ="java2s.com";
    s=  strFunc.apply(name," Java Lambda Tutorial"); 
    System.out.println(s);

  }
  
  @Override
  public String append(String s1,String s2){
    System.out.println("child append");
    return s1+s2;
  }  
}
class ParentUtil{
  public String append(String s1,String s2){
    System.out.println("parent append");
    return s1+s2;
  }  
}

The code above generates the following result.