【响应式编程-05】Lambda方法引用

发布时间:2024年01月06日

一、简要描述

Lambda的方法引用也叫引用方法

  • 方法引用初体验
  • 方法引用的底层实现
  • 方法引用的语法格式
  • 方法引用举例
    • 静态方法引用
    • 构造方法引用
    • 普通方法引用
    • super和this方法引用
    • 数组的方法引用

二、方法引用初体验

为什么出现方法引用?

  • 引用已存在方法,避免重复逻辑
  • 代码更加简洁

Lambda函数体以存在,是否还有存在的必要? 答案是:没有存在的必要,直接方法引用调用。

三、方法引用的底层实现

1、使用cfr工具包解码Lambda字节码

使用java命令,cfr工具解析字节码 java -jar cfr-0.145.jar MethodReferenceFirstGo.class --decodelambdas false

2、使用Java命令打开dumps调试模式

Java命令java -Djdk.internal.lambda.dumpProxyClasses ClassName

打开调试模式

2.1、生成Lambda编译的class文件

生成后编译后的文件:

  • MethodReferenceFirstGo$$Lambda$1.class
  • MethodReferenceFirstGo$$Lambda$2.class

2.2、两个文件进行对比

四、方法引用语法格式

  • 方法引用运算符

????????双冒号 ::

  • 那些方法可以引用?
    • 类方法 / 构造方法 / 实例方法
    • 被引用方法与函数式接口抽象方法:
      • 参数列表相同
      • 返回值类型相同
  • 方法引用语法格式

?????????格式:类名 :: 静态方法

????????????????范例:Integer :: parseIn

????????格式:类名 :: new

????????????????范例:Student :: new

????????格式:对象 :: 成员方法

????????????????范例:hello :: toUpperCase

????????格式:this :: 方法名 / super :: 方法名

五、方法引用示例

1、静态方法引用

1.1、定义Calcable接口类

package tech.flygo.lambda.demo6;

/**
 * @description: 计算数值接口
 * @author: flygo
 * @time: 2023/8/12 11:16
 */
@FunctionalInterface
public interface Calcable {

    /**
     * description: 定义一个抽象方法,传递一个整数,对整数进行绝对值计算并返回 <br>
     * date: 2023/8/12 11:17 <br>
     * author: flygo <br>
     *
     * @return int
     * @param: number
     */
    int calcAbs(int number);
}

1.2、定义StaticMethodReference主函数测试类

package tech.flygo.lambda.demo6;

/**
 * @description: 通过类名引用静态成员方法 <br>
 * 类已经存在,静态成员方法也已经存在 <br>
 * 就可以通过类名直接引用静态成员方法 <br>
 * @author: flygo
 * @time: 2023/8/12 11:18
 */
public class StaticMethodReference {

    /**
     * description: 定义一个方法,方法的参数传递要计算绝对值的整数,和函数式接口Calcable <br>
     * date: 2023/8/12 11:19 <br>
     * author: flygo <br>
     *
     * @return int
     * @param: number
     * @param: c
     */
    public static int method(int number, Calcable c) {
        return c.calcAbs(number);
    }

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

        // 使用方法引用优化Lambda表达式
        /**
         * Math类是存在的
         * abs计算绝对值的静态方法也是存在的
         * 所有我们可以直接通过类名引用静态方法
         */
        int result = method(-20, Math::abs);
        System.out.println(result);
    }
}

1.3、代码示例

2、构造方法引用

2.1、定义Person类

package tech.flygo.lambda.demo7;

/**
 * @description: 人类
 * @author: flygo
 * @time: 2023/8/12 11:45
 */
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;
    }
}

2.2、定义一个创建Person对象的函数式接口

package tech.flygo.lambda.demo7;

/**
 * @description: 定义一个创建Person对象的函数式接口
 * @author: flygo
 * @time: 2023/8/12 11:47
 */
@FunctionalInterface
public interface PersonBuilder {

    /**
     * description: 定义一个方法,根据传递的姓名,创建Person对象返回 <br>
     * date: 2023/8/12 11:48 <br>
     * author: flygo <br>
     *
     * @return tech.flygo.lambda.demo7.Person
     * @param: name
     */
    Person buildPerson(String name);
}

2.3、定义ConstructorMethodReference主函数测试类

package tech.flygo.lambda.demo7;

/**
 * @description: 类的构造器(构造方法)引用
 * @author: flygo
 * @time: 2023/8/12 11:49
 */
public class ConstructorMethodReference {

    /**
     * description: 定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象 <br>
     * date: 2023/8/12 11:50 <br>
     * author: flygo <br>
     *
     * @return void
     * @param: name
     * @param: builder
     */
    public static void printName(String name, PersonBuilder builder) {
        Person person = builder.buildPerson(name);
        System.out.println(person.getName());
    }

    public static void main(String[] args) {

        // 调用printName方法,方法的参数PersonBuilder接口是一个函数式接口,可以传递Lambda表达式
        printName("刘德华", name -> new Person(name));

        // 使用方法引用优化Lambda表达式
        /**
         构造方法 new Person(String name)已知
         创建对象已知 new
         就可以使用Person引用new创建对象
         */
        // 使用Person类带参数的构造方法,通过传递的姓名创建对象
        printName("周欣欣", Person::new);
    }
}

2.4、代码示例和运行结果

3、普通方法引用

3.1、定义一个打印的函数式接口Printable

package tech.flygo.lambda.demo8;

/**
 * @description: 定义一个打印的函数式接口
 * @author: flygo
 * @time: 2023/8/12 12:14
 */
@FunctionalInterface
public interface Printable {
    
    /**
     * description: 定义打印字符串的抽象方法 <br>
     * date: 2023/8/12 12:15 <br>
     * author: flygo <br>
     *
     * @return void
     * @param: s
     */
    void print(String s);
}

3.2、打印字符串的对象类MethodRerObject

package tech.flygo.lambda.demo8;

/**
 * @description: 打印字符串的对象类
 * @author: flygo
 * @time: 2023/8/12 12:15
 */
public class MethodRerObject {

    /**
     * description: 定义一个成员方法,传递字符串,把字符串转换成大写输出 <br>
     * date: 2023/8/12 12:16 <br>
     * author: flygo <br>
     *
     * @return void
     * @param: str
     */
    public void printUpperCaseString(String str) {
        System.out.println(str.toUpperCase());
    }
}

3.3、通过对象名引用成员方法测试类

package tech.flygo.lambda.demo8;

/**
 * @description: 通过对象名引用成员方法
 * 使用前提是对象名是已经存在的,成员方法也是已经存在的
 * 就可以使用对象名来引用成员方法
 * @author: flygo
 * @time: 2023/8/12 12:17
 */
public class ObjectMethodReference {

    /**
     * description: 定义一个方法,方法的参数传递Printable接口 <br>
     * date: 2023/8/12 12:20 <br>
     * author: flygo <br>
     *
     * @return void
     * @param: printable
     */
    public static void printString(Printable printable) {
        printable.print("Hello");
    }

    public static void main(String[] args) {

        // 调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda表达式
        printString(s -> {
            // 创建MethodRerObject对象
            MethodRerObject object = new MethodRerObject();
            // 调用MethodRerObject对象中的成员方法printUpperCaseString,把字符串按照大写输出
            object.printUpperCaseString(s);
        });

        // 创建MethodObject对象
        MethodRerObject object = new MethodRerObject();
        /*
            使用方法引用优化Lambda
            对象是已经存在的MethodRerObject
            成员方法是已经存在的printUpperCaseString
            所以可以使用对象名引用尘缘方法
         */
        printString(object::printUpperCaseString);
    }
}

3.4、示例代码和运行结果

文章来源:https://blog.csdn.net/weixin_42257984/article/details/135433185
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。