Towards Functional Java: Method References

In the previous post of the Towards Functional Java series, we saw how to create a reference to a method implementation using lambda expressions and functional interfaces, passing it as an argument to methods in the same way we are used to pass object references.

Note: to try out the examples in this post, you need a Java 8 development environment. If you do not have one, you can follow this tutorial to set one up.

In the following JUnit test, we implement the functional interface Comparator so that it compares two strings by length (instead of alphabetical order) using a lambda expression, and assign the implementation to the variable comp. We then use the variable name to pass the implementation to the Collections.sort method to sort a List of strings. The API doc can be found here:

https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-java.util.Comparator-

@Test
public void lambdaExpressionTest() {

   Comparator<String> comp = (str1, str2) -> 
       Integer.compare(str1.length(), str2.length());

   List<String> list = new ArrayList<String>();
   list.add("abcd");
   list.add("abcdef");
   list.add("ab");

   Collections.sort(list, comp);

   assertTrue(list.get(0).equals("ab"));
}

 
Now, suppose the above functionality was already provided by a method of an existing class, as in the following example:

public class AlternativeStringComparison {	
   public int compareByLength(String str1, String str2) {
      return Integer.compare( str1.length(), str2.length());
   }
}

 
You can refer to the compareByLength method directly using the following notation:

@Test
public void lengthComparisonTest() {	
   AlternativeStringComparison comp = new AlternativeStringComparison();
      
   List<String> list = new ArrayList<String>();
   list.add("abcd");
   list.add("abcdef");
   list.add("ab");

   Collections.sort(list, comp::compareByLength);

  assertTrue(list.get(0).equals("ab"));	
}

 
The expression comp::compareByLength is called a method reference. In this case we are creating a reference to an instance method, using the notation object::instanceMethodName.

If the instance method is defined by the same class of the receiver object, you can use the notation Class::instanceMethodName. For example, the String class defines an instance method to perform a case-insensitive string comparison. See the API doc:

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#compareToIgnoreCase-java.lang.String-

You can create a reference to it as follows:

@Test
public void caseInsensitiveComparisonTest() {

   List<String> list = new ArrayList<String>();
   list.add("bobby");
   list.add("Andrew");
   list.add("john");

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

   assertTrue(list.get(0).equals("Andrew"));
}

 
Likewise, it is possible to create a reference to a static method with the notation Class::staticMethodName. Consider the following class:

public class AlternativeStringComparison {	
   public static int compareByLen(String str1, String str2) {
      return Integer.compare( str1.length(), str2.length());
   }
}

 
You can create a reference to its static method as follows:

@Test
public void staticLengthComparisonTest() {
		
   List<String> list = new ArrayList<String>();
   list.add("abcd");
   list.add("abcdef");
   list.add("ab");

   Collections.sort(list, AlternativeStringComparison::compareByLen);

   assertTrue(list.get(0).equals("ab"));	
}

 
Constructor methods can be also referenced using the notation Class::new. We will look at practical applications of constructor references in a later post when discussing Java 8 streams.

In summary, four types of method references have been introduced in Java 8:

Type Notation Notes
Reference to a bound instance method object::instanceMethodName  
Reference to an unbound instance method Class::instanceMethodName  
Reference to a static method Class::staticMethodName  
Reference to a constructor Class::new  

In the next post we will look at more Java 8 functional features. Feel free to leave any comments or suggestions. Thank you for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *