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.

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

Popular posts from this blog

Finding Median by Stream

Factorial by Different Styles in Java

Reduction by Java Stream