八 JDK8新特性——第四节 方法引用-优化Lambda

1、方法引用基本介绍

主要对Lambda表达式的优化
在使用Lambda表达式的时候,实际上传递进去的是代码就是一种解决方案,拿什么参数做什么需求,那么考虑一种情况,如果我们在Lambda中所指的操作方案,已经有地方有相同方案,是否需重复?

Lambda要有函数式接口,定义一个函数式接口

package com.company.demo05LambdaTest;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:37
 * 定义一个打印的函数式接口,
 */
@FunctionalInterface
public interface Printable {
    //打印字符串的抽象方法
     void print(String s);
}

定义一个类。

package com.company.demo05LambdaTest;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:39
 */
public class Demo01Printable {
    //定义一个方法,参数传printable接口。对字符串打印
    public static void printString(Printable p ){
        p.print("helloword");
    }

    public static void main(String[] args) {
        //调用printstring方法 ,参数Printable是一个函数式接口,可以传递lambda表达式
        printString((s)->{
            System.out.println(s); //helloword
        });
        /*
 分析
        lambda 表达式的目的,打印参数传递的字符串,把参数s传递给System.out对象,调用out对象的方法println,对字符串输出
        注意:
        1、System.out对象已经存在,
        2、调用其方法println已经存在

       所以可以用方法引用优化lambda
       可以使用System.out直接引用(调用)println方法 ,取代Lambda, 对字符串输出,参数省略
       :: 是方法引用的运算符,表达式是方法引用表达式
       两种写法效果一样,第二种更简洁
       注意:
       Lambda中传递的参数一定是方法引用中的那个方法可以接收的类型,否则抛异常
         */
        printString(System.out::println);  //helloword
    }
}
方法引用符

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

前提: 类存在,静态方法存在

1、对象名要有实例 化的对象,所以要建一个类,实例对象, 类中定义一个成员方法, 通过类创建一个对象,来引用里面的成员方法
类MethodRerObject

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 16:48
 */
public class MethodRerObject {

    //定义一个成员方法,传递字符串,按照大写输出
    public  void printUpString(String str){
        System.out.println(str.toUpperCase());
    }
}

2、函数式接口

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/29 16:37
 * 定义一个打印的函数式接口,
 */
@FunctionalInterface
public interface Printable {
    //打印字符串的抽象方法
     void print(String s);
}

3、测试类

package com.company.demo06ObjectMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 16:51
 * 通过对象名引用成员方法
 * 使用前提:对象名存在,成员方法存在,就可以使用对象名引用成员方法
 */
public class Demo01ObjectMethodRer {
    //定义一个方法。方法的参数传递Printable接口
    public static void printString(Printable p){
        p.print("hello");
    }

    public static void main(String[] args) {
        //调用printString ,方法的参数是函数式接口,可以传递lambda 表达式
        printString((s)->{
            //创建MethodRerObject对象
            MethodRerObject obj = new MethodRerObject();
            //调用对象中的成员方法printUpString,把字符串按照大写输出
            obj.printUpString(s);  //HELLO
        });

        /*使用方法引用优化lambda
        对象MethodRerObject已经存在, 成员方法也存在printUpString
        所以可以用对象名来引用成员方法
         */
        //创建MethodRerObject对象
        MethodRerObject obj2 = new MethodRerObject();
        printString(obj2::printUpString);  //HELLO
    }
}

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

由于在类中java.lang.Math中已经存在了静态方法abs,所以需要通过lambda 调用该方法时,有两种写法,首先是函数式接口,使用lambda , 一种是类名引用静态方法

函数式接口

package com.company.demo07StaticMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 17:08
 */
@FunctionalInterface
public interface Calcable {
    //定义一个抽象方法,传递一个整数,对整数进行绝对值计算,并返回
    public int calAbs(int number);
}

测试类

package com.company.demo07StaticMethod;

/**
 * @author 杜艳艳
 * @version 1.0
 * @date 2020/12/30 17:11
 * 通过类名引用静态成员方法,使用前提:类名存在,静态成员方法存在;就可以直接用类名引用静态成员方法
 */
public class Demo01StaticMethodRer {
   //定义一个方法,方法的参数传递要计算绝对值的整数 和 函数式接口Calcable
    public static int method(int number,Calcable c){
        return c.calAbs(number);
    }

    public static void main(String[] args) {
        //调用method 方法,传递计算绝对值的整数 和 Lambda表达式
        int num = method(-10,(n)->{
            //对参数进行绝对值的计算,并返回结果
            return Math.abs(n);
        });
        System.out.println(num);  //10

        /*通过类名引用静态成员方法。优化lambda表达式
        Math 存在。abs 计算绝对值的静态成员方法存在
        所以可以直接通过类名引用静态方法
         */
        int num2 = method(-10, Math::abs);
        System.out.println(num2);  //10

    }
}

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

如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代
前提: 有子父类继承关系,有函数式接口,父类有成员方法


例子

函数式接口

package con.day13.demo05.SuperMethodReference;

/*
定义一个见面的函数式接口
 */
@FunctionalInterface
public interface Greetable {
   //定义一个见面的方法
    void greet();
}

父类

package con.day13.demo05.SuperMethodReference;

/*
定义父类
 */
public class Human {
    //定义一个sayhello 的方法
    public void sayHello(){
        System.out.println("父类human的sayHellO");
    }
}

子类以及主方法

package con.day13.demo05.SuperMethodReference;
/*
定义子类
 */
public class Man extends Human{
    //重写父类sayHello的方法

    @Override
    public void sayHello() {
        System.out.println("我是子类");
    }

    //定义一个方法参数传递Greetable接口
    public void method(Greetable g){
        g.greet();
    }

    public void show(){
        //调用method 方法,方法的参数是函数式接口,可传递Lambda
       /* method(()->{
            //创建父类对象
            Human h = new Human();
            //调用父类的sayHello
            h.sayHello();
        });*/
        //因为有子父类关系,可以存在一个关键字super 所以我们可以直接用super调用父类的成员方法

       /* method(()->{
            super.sayHello();    //父类human的sayHellO
        });*/

        //继续简化, 使用super引用父类的成员方法, super 已经存在,sayHello 已经存在,
        //所以可直接使用super引用父类的成员方法
        //父类human的sayHellO
        method(super::sayHello);
    }

    public static void main(String[] args) {
        new Man().show();  //父类human的sayHellO
    }
}

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

this

函数式接口

package con.day13.demo05.ThisMethodReference;

/*
定义一个函数式接口
 */
@FunctionalInterface
    public interface Richable {
        //想买什么就买什么的方法
        void buy();
    }

方法:

package con.day13.demo05.ThisMethodReference;

/*
通过this引用本类的成员方法
 */
public class Husband {
    //定义一个买房子的方法
    public void buyHouse(){
        System.out.println("买到房子啦");
    }
    //定义结婚方法,参数传递Richable接口
    public void marry(Richable r){
        r.buy();
    }

/*    //定义一个非常高兴的方法
    public void soHappy(){
        //调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
        marry(()->{
            //使用this.成员方法,调用本类买房子的方法
            this.buyHouse();  //买到房子啦
        });
    }*/

    //简化, 方法引用

    //定义一个非常高兴的方法
    public void soHappy(){
        //调用结婚方法。方法的参数Richable 是一个函数式接口,用Lambda
        marry(this::buyHouse);  //买到房子啦;
    }


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

6、 方法引用-类的构造器引用

Person 类

package con.day13.demo05.ConstructorMethodReference;

public class Person {
    private String name;

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

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

函数式接口

package con.day13.demo05.ConstructorMethodReference;
//创建Perso对象的函数式接口
@FunctionalInterface
public interface PersonBuilder {
    //定义一个方法,根据传递的姓名,创建Person 对象返回
    Person builderPerson(String name);
}

方法类

package con.day13.demo05.ConstructorMethodReference;

/*
类的构造器引用
 */
public class Demo {
    //定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
    public static void pringName(String name, PersonBuilder pb){
        Person person = pb.builderPerson(name);
        System.out.println(person.getName()); //迪丽热巴
    }

/*    public static void main(String[] args) {
        //调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
        pringName("迪丽热巴",(String name)->{
            return new Person(name);
        });
    }*/
/*使用方法引用,优化
构造方法new Person(String name)已知
创建对象已经new
就可以使用Person引用new创建对象
    */
    public static void main(String[] args) {
        //调用pringName方法,方法的参数是PersonBuilder ,函数式接口,用Lambda
        pringName("迪丽热巴", Person::new);
    }
}

7、方法引用-数组的构造引用

你可能感兴趣的:(八 JDK8新特性——第四节 方法引用-优化Lambda)