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
@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:
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.
