Method References by the Double-colon Separator :: in Java
The double-colon separator :: has been available since Java 8. The purpose is to provide a way to refer to a method without executing it. Method reference is similar to the sense of Lambda expression in that it requires a target method that fits in a functional interface.
Procedural programming requires passing variables or objects as parameters. Now with method references, we can pass a method as a parameter. The double-colon :: separator allows references to static methods or instance methods. The syntax of both is similar. The below example demonstrates the use of method references to static methods.
In this example, I did not create my interfaces. I used the predefined interfaces in the java.util.function package: UnaryOperator<T>, and Function<T, U>. Using those standard interfaces in the core Java library helps enforcing consistency. It is also convenient to use existing code that is well written.
The program produces this result:
There was wind that I listened to and smoothness that I saw.
There was wind that we listened to and smoothness that we saw.
There was wind that we listened to and smoothness that we saw. -- Calmalgo
Number of words: 13
Procedural programming requires passing variables or objects as parameters. Now with method references, we can pass a method as a parameter. The double-colon :: separator allows references to static methods or instance methods. The syntax of both is similar. The below example demonstrates the use of method references to static methods.
import java.util.function.*; class MyTools { // This class contains some simple static methods. static String changeI2We (String s) { return s.replaceAll("I", "we"); } static String addAuthor (String s) { return s + " -- Calmalgo"; } static Integer countWords (String s) { String[] punctuations = {"\\--", "\\.", "\\,"}; for (String x : punctuations) s = s.replaceAll(x, " "); s = s.replaceAll("\\s+", " "); return s.split(" ").length; } } class MethodRefPlay { // This method takes in two parameters. The first parameter is a method that fits // the UnaryOperator interface; the second a String. static String stringOp (UnaryOperator<String> uo, String s) { return uo.apply(s); } // This method takes in two parameters. The first parameter is a method that fits // the Function interface; the second a String. static Integer countInString (Function<String, Integer> f, String s) { return f.apply(s); } public static void main(String args[]) { var text = "There was wind that I listened to and smoothness that I saw."; System.out.println (text); // Refer to the replaceI2We method of the MyTools class, and apply the method to the String. var weText = stringOp (MyTools::changeI2We, text); System.out.println (weText); // Refer to the addAuthor method of the MyTools class, and apply the method to the String. var weTextAuthor = stringOp (MyTools::addAuthor, weText); System.out.println (weTextAuthor); // Refer to the countWords method of the MyTools class, and apply the method to the String. var numWords = countInString (MyTools::countWords, weTextAuthor); System.out.println ("Number of words: " + numWords); } }
In this example, I did not create my interfaces. I used the predefined interfaces in the java.util.function package: UnaryOperator<T>, and Function<T, U>. Using those standard interfaces in the core Java library helps enforcing consistency. It is also convenient to use existing code that is well written.
The program produces this result:
There was wind that I listened to and smoothness that I saw.
There was wind that we listened to and smoothness that we saw.
There was wind that we listened to and smoothness that we saw. -- Calmalgo
Number of words: 13
Comments
Post a Comment