【函数式编程】方法引用

方法引用

什么是方法引用

  1. 方法引用是Lambda表达式的一种特殊形式。
  2. 方法引用提供了一种更简洁的方式来为Lambda参数指定现有的方法或构造器。
  3. 方法引用需要一个与现有方法声明兼容的函数式接口。
  4. 方法引用语法为:Classname::methodName

使用方法引用

举个例子就懂了,使用已经存在的方法去替换我们的Lambda表达式。

一般函数表达式写法:

csharp 复制代码
public class MyClass{
    public static void main(String[] args) {
        addMethod(5,6,(a,b) -> a+b);
    }
    public static int addMethod(int a, int b, MyFunction myFunction){
        return myFunction.add(a,b);
    }
}
@FunctionalInterface
interface MyFunction {
    int add(int a, int b);
}

使用方法引用:

csharp 复制代码
public class MyClass{
    public static void main(String[] args) {
        addMethod(5,6, Integer::sum);
    }
    public static int addMethod(int a, int b, MyFunction myFunction){
        return myFunction.add(a,b);
    }
}
@FunctionalInterface
interface MyFunction {
    int add(int a, int b);
}

可以看到: 我的函数式表达式(a,b) -> return a+b替换为Integer::sum, 把代码拷贝下来跑一跑。

为什么可以这样替换呢?

因为它们的逻辑与方法相同(Integer的sum函数是求和,而我的函数式接口也是求和,方法的逻辑相同,参数列表也相同),就可以直接替换。

Integer类的sum方法:

arduino 复制代码
public static int sum(int a, int b) {
    return a + b;
}

是不是和我的add方法一模一样呢。

方法引用的好处

那替换有什么好处呢?

  • 更简洁 - 不需要具体参数列表
  • 更易读 - 方法名直接说明功能
  • 代码复用 - 使用已经存在的函数,不用自己再去构造,效率肯定比自己写更高

方法引用的主要形式包括:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
  • 类构造器::new
  • 数组类型[]::new

下面对四种形式进行举例子

对象::实例方法

创建类的实例,再去使用它的方法

typescript 复制代码
public class MyClass{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.test();
    }
    public void test(){
        // 创建实例
        Cat cat = new Cat();
        // 定义消费者接口
        Consumer<String> cs1 = (s) -> System.out.println("cat eat " + s);
        Consumer<String> cs2 = cat::eat;
        // 调用方法
        cs1.accept("fish");
        cs2.accept("fish");
    }
}
class Cat{
    public void eat(String s){
        System.out.println("cat eat " + s);
    }
}

类::静态方法

直接使用类的静态方法

typescript 复制代码
public class MyClass{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.test();
    }
    public void test(){
        // 定义消费者接口
        Consumer<String> cs1 = (s) -> System.out.println("cat eat " + s);
        Consumer<String> cs2 = Cat::eat;
        // 调用方法
        cs1.accept("fish");
        cs2.accept("fish");
    }
}
class Cat{
    public static void eat(String s){
        System.out.println("cat eat " + s);
    }
}

类::实例方法

ini 复制代码
// 方法引用-类名::实例方法名
BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
BiFunction<String, String, Boolean> fun2 = String::equals;
Boolean result2 = fun2.apply("hello", "world");
System.out.println(result2);

这个只能使用JavaJDK已经编写好的类的函数,自己编写的函数需要设为static。

类构造器::new

typescript 复制代码
public class Solution {
    public static void main(String[] args) {
        // 使用lambda表达式
        Function<String, Cat> f1 = (s)-> new Cat(s);
        Cat c1 = f1.apply("小白");
        System.out.println(c1.getName());
        // 使用方法引用
        Function<String, Cat> f2 = Cat::new;
        Cat c2 = f2.apply("小黑");
        System.out.println(c2.getName());
    }
}
class Cat{
    private String name;
    Cat(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
}

注意: 使用的时候传入的参数列表需要和构造函数相匹配。比如我里面用的Fuction接口,刚刚好就是我们Cat类的对应形式,构造函数返回值为它的类对象

如果要匹配多个参数怎么办???

答案是我们自己定义函数接口呗,比如定义一个接收三个参数的:

scss 复制代码
@FunctionalInterface
interface CatFactory<T,V,R>{
    Cat getCat(T a1, V a2, R a3);
}

数组类型[]::new

typescript 复制代码
public class Solution {
    public static void main(String[] args) {
       ArrayFactory<String> af = String[]::new;
        String[] strings = af.create(5);
    }
}
@FunctionalInterface
interface ArrayFactory<T> {
    T[] create(int size);
}
相关推荐
哎呦没19 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch38 分钟前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries3 小时前
读《show your work》的一点感悟
后端
A尘埃3 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23073 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code3 小时前
(Django)初步使用
后端·python·django
代码之光_19803 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端
编程老船长3 小时前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
IT果果日记3 小时前
DataX+Crontab实现多任务顺序定时同步
后端