webflux 之 lambda

首先先说明一下,Lambda是java提供的,Spring webFlux编程中要用大量的lambda表达式完成编码,所以这里先简要介绍下Lambda

编程类型对比

函数式编程:实现功能并不关心具体实现细节(大部分jdk提供)
命令式编程:程序描述具体实现细节

Lambda表达式介绍

参数列表  -> 代码块

举例:

() -> System.out.println("ok");

返回值是Runnable接口类型

相同的一个lambda表达式调用两次返回结果不相同。

函数接口

为了声明lambda表达式入参和返回值类型,定义的接口。只能有一个方法。

@FunctionalInterface
interface interface1 {
	int doubleNum(int i);
	
	//默认方法,如果继承中含有二义性,选择继承那个方法。
	default int add(int x, int y){
		return x+y;
	}
}


Interface1 i1 = (i) -> i * 2;

//调用定义的函数
System.out.println(i1.doubleNum(20));

//调用默认的函数
System.out.println(i1.add(3, 7));

本文所写代码都是在jdk8环境下完成。

代码:说明方法引用的几种方法

class Dog{
    /**
     * JDK会默认把当前实例传入到非静态方法,参数名为this,位置是第一个
     * @param args
     */

    private  String name = "哮天犬";

    private  int food = 10;

    public Dog(){

    }

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

    /**
     * 静态方法
     */
    public static void bark(Dog dog){
        System.out.println(dog + "叫了");
    }

    public  int eat(int num){
        System.out.println("吃了" + num + "");
        this.food -= num;
        return this.food;
    }

    @Override
    public String toString() {
        return this.name;
    }
}

public class MethodReference {

    public static void main(String[] args) {

        //消费函数lambda
        Consumer<String> consumer = s -> System.out.println(s);
        consumer.accept("输入的数据");

        //方法引用
        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("输入的数据");

        //静态方法的引用,使用类名引用
        Consumer<Dog> consumer2 = Dog::bark;
        Dog dog = new Dog();
        consumer2.accept(dog);

        //非静态方法,使用实例对象引用
        //指定参数和返回值类型
//        Function<Integer, Integer> function = dog::eat;

        //入参和返回值类型相同
        UnaryOperator<Integer> function = dog::eat;
        System.out.println("还剩下" + function.apply(2) + "斤");

        //使用特定结构体
        IntUnaryOperator function1 =  dog::eat;
        //如果实例是null,不会影响函数结果
//        dog = null;   //屏蔽,下面还会用到
        System.out.println("还剩下" + function1.applyAsInt(2) + "斤");

        //非静态方法,使用类名引用,Dog:eat;
        BiFunction<Dog, Integer, Integer> eatFunction = Dog::eat;
        System.out.println(eatFunction.apply(dog, 3));

        //构造函数的引用
        Supplier<Dog> supplier = Dog::new;
        System.out.println("创建了新对象: " + supplier.get());

        //带参数的构造函数的方法引用
        Function<String, Dog> function3 = Dog::new;
        System.out.println("创建了新对象:"+ function3.apply("旺财"));
    }
}
//输出结果:
//输入的数据
//输入的数据
//哮天犬叫了
//吃了2
//还剩下8斤
//吃了2
//还剩下6斤
//吃了3
//3
//创建了新对象: 哮天犬
//创建了新对象:旺财

 lambda 返回值类型推断

/**
 * 类型推断
 */
@FunctionalInterface
interface IMath{
    int add(int x, int y);
}

public class TypeDemo {

    public static void main(String[] args) {

        //变量类型定义
        IMath lambda = (x,y) -> x+y;

        //数组里
        IMath[] lambda1 = {(x,y)->x+y};

        //强转
        Object lambda2 = (IMath)(x,y)->x+y;

        //通过返回类型
        IMath creatLambda = createLambda();

        TypeDemo typeDemo = new TypeDemo();
        //如果存在多个重载方法参数是接口,可以使用强转
        typeDemo.test((x,y)->x+y);

    }

    public void test(IMath math){

    }

    public static IMath createLambda(){
        return (x,y) -> x+y;
    }
}

变量引用

在将集合传入内部函数之后,不要修改集合变量,容易产生歧义。即外部改变了之后导致内部和外部引用指向的不是同一个对象。

扫描二维码关注公众号,回复: 10446363 查看本文章

级联表达式和柯里化

/**
 * 级联表达式和柯里化
 */
public class CurryDemo {

    public static void main(String[] args) {

        //实现级联表达式
        Function<Integer, Function<Integer, Integer>> function = x->y->x+y;
        System.out.println(function.apply(2).apply(3));

        //柯里化就是把多个参数的函数转化为只有一个参数的函数
        //目的:函数标准化,便于重复使用
        //高阶函数:返回函数的函数
    }
}

lambda底层实现原理 

/**
 * lambda底层实现原理
 * 
 * 1. 编译器会为每一个lambda表达式生成一个方法
 * 		方法名是lambda$0,1,2,3,但方法引用的表达式不会生成方法。
 * 2. 在lambda地方会产生一个invokeDynamic指令,这个指令会调用
 * 		bootstrap(引导)方法,bootstrap方法会指向自动生成的lambda$0
 * 		方法或者方法引用的方法。
 * 3. bootstrap方法使用上是调用了LambdaMetafactory.metafactory静态方法
 * 		该方法返回了CallSite(调用站点),里面包含了MethodHandle(方法句柄)
 * 		也就是最终调用的方法。
 * 4. 引导方法只会调用一次。
 * 
 * 自动生成的方法:
 * 1. 输入和输出和lambda一致
 * 2. 如果没有使用this,那么就是static方法,否则就是成员方法
 *
 */
发布了155 篇原创文章 · 获赞 11 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013919153/article/details/104973476