【函数式编程】方法引用

方法引用

什么是方法引用

  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);
}
相关推荐
会说法语的猪42 分钟前
springboot实现图片上传、下载功能
java·spring boot·后端
凡人的AI工具箱1 小时前
每天40分玩转Django:实操多语言博客
人工智能·后端·python·django·sqlite
Cachel wood1 小时前
Django REST framework (DRF)中的api_view和APIView权限控制
javascript·vue.js·后端·python·ui·django·前端框架
m0_748234081 小时前
Spring Boot教程之三十一:入门 Web
前端·spring boot·后端
想成为高手4991 小时前
国产之光--仓颉编程语言的实战案例分析
后端
编码浪子2 小时前
构建一个rust生产应用读书笔记7-确认邮件2
开发语言·后端·rust
昙鱼2 小时前
springboot创建web项目
java·前端·spring boot·后端·spring·maven
白宇横流学长2 小时前
基于SpringBoot的停车场管理系统设计与实现【源码+文档+部署讲解】
java·spring boot·后端
kirito学长-Java2 小时前
springboot/ssm太原学院商铺管理系统Java代码编写web在线购物商城
java·spring boot·后端
程序猿-瑞瑞3 小时前
24 go语言(golang) - gorm框架安装及使用案例详解
开发语言·后端·golang·gorm