Java 8 Method Reference

Content Introduction:

  1. Method Reference Demo Details
  2. Reference through five grammatical usage methods
  3. Method Reference Usage Summary

1. Method Reference Demo in Java 8

1.1 Background for Methodological References

When we use Lambda expressions, the code we actually pass in is a solution: what parameters to do with.
So consider a case: if we already have the same solution in place for the operation scheme specified in Lambda, is it necessary to write duplicate logic again?

Introduction of 1.2 Problem

    //Functional interface for printing strings.
    @FunctionalInterface
    interface Print{
        public void print(String s);
    }

    //Use lambda expression to complete the case test.
    public class PrintDemo {

        public static void main(String[] args) {
            //Lambda Solution
            print(s -> {System.out.println(s);}, "hello");
        }

        public static void print(Print p,String s){
            p.print(s);
        }
    }

    //Output results:
            hello

1.3 Problem Discovery and Solution

The problem with this code is that the println(String) method in the System.out object has already been implemented to print out the String control console. Since what Lambda wants to do is call the println(String) method, why call it manually?
Can you omit Lambda's grammatical format (although it's already quite concise)? As long as "routing" goes by:
    //Functional interface for printing strings.
    @FunctionalInterface
    interface Print{
        public void print(String s);
    }

    //Use lambda expression to complete the case test.
    public class PrintDemo {

        public static void main(String[] args) {
            //Method Reference Solution
            //Note that the double colon ":" is called "method reference" and the double colon is a "reference operator".
            print(System.out :: print,"world");
        }

        public static void print(Print p,String s){
            p.print(s);
        }
    }

    //Output results:
            world

1.4 Summary of Methodological Reference Cases

In the above example, an overloaded println(String) method in the System.out object is exactly what we need. Then for the printString method's functional interface parameters, compare the following two writings:
Lambda expression: s - > System. out. println (s);
Method reference: System.out::println
 The first kind of semantics refers to: after getting the parameters, it is handled by Lambda and then passed to System.out.println method. The semantics of the second kind of equivalent writing refers to the direct substitution of the println method in System.out for Lambda. The execution effect of the two methods is exactly the same, while the second method uses the existing scheme and is more concise.

1.5 Reference Operator

The double colon ":" is a reference operator, and its expression is called a method reference. If the function scheme Lambda is expressing already exists in the implementation of a method, it can be referred to as a substitute for Lambda by double colons.

2. Reference through five grammatical usage methods

2.1 Reference to member methods by object names

    //Functional interface
    @FunctionalInterface
    interface Printable{
        public void print(String s);
    }

    //Existing classes have methods for printing strings.
    class AlreadyExistPrint{

        public void PrintString(String s){
        System.out.println(s);
    }

    //Tests refer to methods by object names.
    public class ObjectMethodReference {

        public static void main(String[] args) {
            //Reference method by object name
            AlreadyExistPrint ap = new AlreadyExistPrint();
            print(ap :: PrintString,"java");
        }

        public static void print(Printable p,String s){
            p.print(s);
        } 

    }

    //Output results:
            java

2.2 Reference to static methods by class name

    //Functional interface
    @FunctionalInterface
    interface MyMath{
        int max(int a, int b);
    }

    //Existing classes
    //The static method max(int a,int b) in the Math class provided by JDK is used here.

    //The test references static methods by class name.
    public class ClassStaticMethod {

        public static void main(String[] args) {
            //The static method max() is referenced by the class name of the Math class.
            int max = getMax(Math :: max, 10, 20);
            System.out.println(max);
        }

        public static int getMax(MyMath lambda ,int a,int b){
            return lambda.max(a, b);
        }

    }

    //Output results:
            20

2.3 Reference to member methods by class name

    /*
    Membership methods need to rely on objects to execute, so when there is no object, member methods cannot execute.
    If you want only class names to appear in the reference of member methods without object names, the situation is more complicated:
    You must specify an object instance for it to execute member methods.
    */

    //Object instances are added to the parameters of functional interfaces:
    @FunctionalInterface
    interface Printable{
        public void print(AlreadyExistPrint a ,String s);
    }

    //Existing classes
    class AlreadyExistPrint{

        public void PrintString(String s){
            System.out.println(s);
        }

    }

    //The test refers to member methods by class name.
    public class ClassMethod {
        public static void main(String[] args) {
            //Referencing member methods by class names;
            //lambda implementation: 
            //Semantic parsing: take object a to call print method of a to print s 
            print((a,s) -> {a.PrintString(s);},new AlreadyExistPrint(),"hello");

            //Simplified Writing: Method Reference (Referring to Membership Methods by Class Name)
            print(AlreadyExistPrint :: PrintString,new AlreadyExistPrint(),"hello");

        }

        public static void print(Printable p ,AlreadyExistPrint a,String s){
            p.print(a,s);
        } 

    }

    //Output results:
            hello
            hello

2.4 Reference to member methods through super

    //Functional interface
    @FunctionalInterface
    interface Eat{
        void eat(String food);
    }

    //Existing classes
    class Animal{
        public void eat(String food){
            System.out.println("eat:"+food);
        }
    }

    //Subclasses of Animal
    class Cat extends Animal{

        @Override
        public void eat(String food) {
            //Refer to the method of the parent class by super.
            method(super :: eat,food);
        }

        public void method(Eat e, String s){
            e.eat(s);
        }
    }

    //The test refers to member methods by class name.
    public class SuperMethod {

        public static void main(String[] args) {
            Cat c = new Cat();
            c.eat("fish");
        }

    }

    //Output results:
            //Eat fish

2.5 Reference to member methods through this

    //Functional interface
    interface shopping {
        void buy(int money);
    }

    //Existing classes
    class Man {
        //Men will buy their own houses in the future.
        public void buyHouse(int money) {
            System.out.println("Buying a house for consumption:"+money);
        }

        //If you get married, you have to go shopping.
        public void marry(shopping lambda,int money) {
            lambda.buy(money);
        }

        //The way to be happy. If a man wants to be happy, he has to get married.
        public void beHappy() {
            //Refer to member methods through this.
            marry(this::buyHouse,1000000);
        }
    }

    //The test refers to member methods by class name.
    public class ThisMethod {

        public static void main(String[] args) {
            Man man = new Man();
            man.beHappy();
        }
    }

    //Output results:
            //Buying a house: 1000000

3. Summary of Method Reference Use

(1) Lambda expression: s - > System. out. println (s);
(2) Method reference: System.out::println

The first kind of semantics refers to: after getting the parameters, it is handled by Lambda and then passed to System.out.println method.

The semantics of the second kind of equivalent writing refers to the direct substitution of the println method in System.out for Lambda.
The execution effect of the two methods is exactly the same, while the second method uses the existing scheme and is more concise.

Functional interfaces are the basis of Lambda, and method references are the twin brothers of Lambda.

Keywords: Java Lambda JDK

Added by lesolemph on Thu, 08 Aug 2019 12:12:29 +0300