方法的引用第二版(method reference)

1、冗余的Lambda场景 

  • 在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。
  • 那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方在相同方案,那是否还有必要再写重复逻辑?
package com.methodreference;

public class MethodReference {

    public static void main(String[] args) {

        printString((s) -> System.out.println(s));
        
        /**
         * 分析:
         *     Lambda表达式的目的,打印参数传递的字符串
         *     把参数s,传递给了System.out对象,调用out对象中的方法println对字符串进行了输出
         *     注意:
         *         1.System.out对象是已经存在的
         *         2.println方法也是已经存在的
         *     所以我们可以使用方法引用来优化Lambda表达式
         *     可以使用System.out方法直接引用(调用)println方法
         */

        printString(System.out::println);
    }

    public static void printString(Printable p) {
        p.print("HelloWorld");
    }


}

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

2、方法引用符

  • 双冒号::为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

3、语义分析

        例如上例中,System.out对象中有一个重载的println(String)方法恰好九四我们所需要的。那么对于printString方法的函数式接口参数,对比下面两种写法,完全等效:

  • Lambda表达式写法:s  ->  System.out.println(s);
  • 方法引用写法:System.out : : println
  1. 第一种语言是指:拿到参数之后经Lambda之手,继而传递给System.out.println方法去处理。
  2. 第二种等效写法的语义是指:直接让System.out中的println方法来取代Lambda。两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简介。

注意:Lambda中传递的参数一定是方法引用中的哪个方法可以接收的类型,否则会抛出异常

4、通过对象名引用成员方法 

  • 通过对象名引用成员方法
  • 使用前提是对象名是已经存在的,成员方法也是已经存在
  • 就可以使用对象名来引用成员方法
package com.methodreference;

public class Demo01ObjectMethodReference {

    public static void main(String[] args) {

        printString(s -> {
            MethodRerObject obj = new MethodRerObject();

            obj.printUpperCaseString(s);
        });

        /**
         * 使用方法引用优化Lambda
         * 对象是已经存在的MethodRerObject
         * 成员方法也是已经存在printUpperCaseString
         * 所以我们可以使用对象名引用成员方法
         */

        MethodRerObject obj = new MethodRerObject();
        printString(obj::printUpperCaseString);

    }

    public static void printString(Printable p) {
        p.print("Hello");
    }
}

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

class MethodRerObject {
    public void printUpperCaseString(String str) {
        System.out.println(str.toUpperCase());
    }
}

 5、通过类名引用静态成员方法

  • 通过类名引用静态成员方法
  • 类已经存在,静态成员方法也已经存在
  • 就可以通过类名接引用静态成员方法
package com.methodreference;

public class Demo01StaticMethodReference {

    public static int method(int number, Calcable c) {
        return c.calsAbs(number);
    }

    public static void main(String[] args) {
        int method = method(-10, (number) -> {
            return Math.abs(number);
        });

        System.out.println(method);//10

        /**
         *  使用方法引用优化Lambda
         *  Math类是存在的
         *  abs计算绝对值的静态方法也是已经存在的
         *  所以我们可以直接通过类名引用静态方法
         */

        int number2 = method(-20, Math::abs);

        System.out.println(number2);//20
    }

}

interface Calcable {
    int calsAbs(int number);
}

6、通过super引用父类的成员方法 

package com.methodreference;

interface Greetable {
    void greet();
}
class Human {
    public void sayHello() {
        System.out.println("Hello我是Human!");
    }
}

public class Man extends Human {

    @Override
    public void sayHello() {
        System.out.println("Hello我是Man!");
    }
    public void method(Greetable g) {
        g.greet();
    }

    public void show() {
//        method(() -> {
//            Human h = new Human();
//            h.sayHello();
//        });

        /**
         * 因为有子父类关系,所以存在的一个关键字super,代表父类,
         * 所以我们可以直接使用super调用父类的成员方法
         */

//        method(()->{
//            super.sayHello();
//        });

        /**
         * 使用super引用类的成员方法
         * super是已经存在的
         * 父类的成员方法sayHello也是已经存在的
         * 所以我们可以直接使用super引用父类的成员方法
         */

        method(super::sayHello);

    }

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

 7、通过this引用本类的成员方法

package com.methodreference;

public class Husband {

    public void buyHouse() {
        System.out.println("河南二环内买一套四合院!");
    }

    public void marry(Richable r) {
        r.buy();
    }

    public void soHappy() {
//        marry(()->{
//            this.buyHouse();
//        });
        /**
         *  使用方法引用优化Lambda表达式
         *  this是已经存在的
         *  本类的成员方法buyHouse也是已经存在的
         *  所以我们可以直接使用this引用本类的成员方法buyHouse
         */

        marry(this::buyHouse);//河南二环内买一套四合院!
    }

    public static void main(String[] args) {
            new Husband().soHappy();
    }

}
@FunctionalInterface
interface Richable {
    void buy();
}

 8、类的构造器引用

package com.methodreference;

public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
@FunctionalInterface
interface PersonBuilder {
    Person builderPerson(String name);
}

class Demo {
    public static void printName(String name,PersonBuilder pb) {
        Person person = pb.builderPerson(name);
        System.out.println(person.getName());
    }

    public static void main(String[] args) {
        printName("小明", (String name) -> {
            return new Person(name);
        });//小明

        /**
         *  使用方法引用优化Lambda表达式
         *  构造方法new Person(String name)已知
         *  创建对象已知 new
         *  就可以使用Person引用new创建对象
         */

        printName("小红",Person::new);//小红
    }
}

9、数组的构造器引用

package com.methodreference;

import java.util.Arrays;

public class Demo {

    public static int[] crateArray(int length,ArrayBuilder ab) {
        return ab.builderArray(length);
    }

    public static void main(String[] args) {
        int[] arr1 = crateArray(10, (length -> {
            return new int[length];
        }));

        System.out.println(arr1.length);

        /**
         *  使用方法引用优化Lambda表达式
         *  已知创建的就是int[]数组
         *  数组的长度也是已知的
         *  就可以使用方法引用
         *  int[] 引用new,根据参数传递的长度来创建数组
         */
        int[] arr2 = crateArray(20, int[]::new);
        System.out.println(Arrays.toString(arr2));
        System.out.println(arr2.length);

    }
}

@FunctionalInterface
interface ArrayBuilder {
    int[] builderArray(int length);
}

你可能感兴趣的:(#,方法引用,java,Lambda,方法的引用)