lambda函数引用学习记录

本文详细介绍了Java 8中Lambda表达式和函数引用的应用,包括接口实现、类::静态方法、实例对象::方法、类::普通方法、类::new的使用场景。通过实例演示,展示了如何通过函数引用提升代码简洁性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

lambda表达式

当一个函数中的参数有一个接口,并且接口中只有一个需要实现的方法(java8之后接口中可以有默认方法default修饰)

比如接口:
	interface MyInterface{
        public void print(String a);
    }
方法
	public void do1(MyInterface myInterface){
        myInterface.print("aaa");
    }
使用
	@Test
    public void test(){
    	//传统方式
        do1(new MyInterface() {
            @Override
            public void print(String a) {
            	System.out.println(a);
            }
        });
        //lambda表达式
        do1((s1)->{System.out.println(s1);});
        //简化
        do1(s1-> System.out.println(s1));
    }

函数引用

常用的几种形式
形式lambda表达式函数引用注释
类::静态方法(arg1,arg2)->{类.静态方法(arg1,arg2)};类::静态方法参数全部作为静态方法中的参数
实例对象::方法(arg1,arg2)->{示例对象.普通方法(arg1,arg2)};实例对象::普通方法参数全部作为普通方法中的参数
类::普通方法(arg1,arg2)->{arg1.普通方法(arg2)};类::普通方法第一个参数作为调用者,之后的全部作为普通方法中的参数
类::new(arg1,arg2)->{new 类(arg1,arg2)};类::new参数全部作类的构造函数参数,类必须提供与接口参数类型个数一致的构造方法
1、类::静态方法

接口中的方法需要我们自己实现逻辑,那么如果有已经定义好的相似结构方法我们是不是直接引用即可,可能你还是很懵。下面直接上例子
上面的System.out.println(s1)其实就是已经定义好类直接调用方法,可以看println方法的声明和我们接口中的方法声明结构是一致的

	@Test
    public void test(){
        do1(s -> System.out.println(s));
        do1(System.out::println);
    }
    public void do1(Consumer<String> consumer){
        System.out.println("function");
        consumer.accept("aa");
    }

在这里插入图片描述

总结:System.out.println()方法可以直接调用,也就是类似于类调用静态方法这种形式,
接口中的方法参数全部作为调用的静态方法中的参数,这就是类::静态方法这种函数引用形式

2、实例对象::方法

例子:

	@Test
    public void test(){
        A a = new A();
        //do1((s1,s2)->a.service(s1,s2));
        do1(a::service);
    }
    public void do1(BiConsumer<String,String> consumer){
        consumer.accept("aaa","bbb");
    }
    class A{
        private void service(String a,String b){
            System.out.println(a+b);
        }
    }

总结接口中的参数作为普通方法的参数

//接口
consumer.accept("aaa","bbb");
//lambda
do1((s1,s2)->a.service(s1,s2));
do1(a::service);
//普通方法
service(String a,String b) 

在这里插入图片描述

3、类::普通方法
接口中只有一个参数,普通方法就没有参数
	@Test
    public void test2(){
        BiConsumer<Lambda2, String> print = Lambda2::print;
        do2(print);
    }
    public void print(String b){
        System.out.println(b);
    }
    public void do2(BiConsumer<Lambda2, String> print){
        print.accept(new Lambda2(),"aaaaa");
    }

在这里插入图片描述

接口中两个参数,普通方法中一个参数
	@Test
    public void test2(){
        Consumer<Lambda2> print = Lambda2::print;
        do2(print);
    }
    public void print(){
        System.out.println("a");
    }
    public void do2(Consumer<Lambda2> print){
        print.accept(new Lambda2());
    }

上面是自定义类的普通方法,下面是一个使用String类的普通方法

	@Test
    public void test3(){
        BiFunction<String,Integer,String> function=String::substring;
        do3((str,index)->str.substring(index));
        do3(String::substring);
    }
    public void do3(BiFunction<String,Integer,String> function){
        String str = function.apply("abcdefg", 2);
        System.out.println(str);
    }

在这里插入图片描述
接口中的第一个参数作为调用者,后面的参数作为普通方法的参数

4、类::new
	@Test
    public void test(){
        do1(User::new);
    }
    public void do1(BiFunction<String,Integer,User> function){
        User user = function.apply("jack", 20);
        System.out.println(user);
    }
    @Data
    class User{
        private String username;
        private Integer age;
        public User(String username, Integer age) {
            this.age=age;
            this.username=getUsername();
        }
    }

参数全部作类的构造函数参数,类必须提供与接口参数类型个数一致的构造方法
在这里插入图片描述

补充

引用的方法有重载怎么确定用的哪个方法?

例如:String的subString方法
	 public String substring(int beginIndex)
	 public String substring(int beginIndex, int endIndex)

答:是根据函数式接口中声明的方法参数来确定

	@Test
    public void test3(){
        BiFunction<String,Integer,String> function=String::substring;
        do3((str,index)->str.substring(index));
        do3(String::substring);
        TriFunction<String, Integer, Integer, String> function1 = String::substring;
        do4((str,index,off)->str.substring(index,off));
        do4(String::substring);
    }
    public void do3(BiFunction<String,Integer,String> function){
        String str = function.apply("abcdefg", 2);
        System.out.println(str);
    }
    public void do4(TriFunction<String,Integer,Integer,String> function){
        String str = function.apply("abcdefg", 2,4);
        System.out.println(str);
    }

在这里插入图片描述

当然 如果不想用与接口方法对应的重载方法,那么就不能使用函数引用,回归到lambda表达式
	@Test
    public void test4(){
        do5((str,index,off)->{return str.substring(index);});
        do5((str,index,off)-> str.substring(index));
    }
    public void do5(TriFunction<String,Integer,Integer,String> function){
        String str = function.apply("abcdefg", 2,4);
        System.out.println(str);
    }

总结

函数引用就是将已经定义好的方法直接拿过来用,必须保证函数式接口声明与调用的方法结构。更像是一种约定,代码简洁了,但得按照更严格的格式。除了类::普通方法这种引用,接口的第一个参数作为调用者,后面的参数作为普通方法的参数、其他形式的引用都是把接口的全部参数作为调用方法的全部参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值