栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Lambda表达式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Lambda表达式

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。Lambda表达式是jdk1.8才有的一种新特性。
为什么会有Lambda表达式
我们写了这样一个计算器类,类中现在有一个加法和一个减法。

public class Calculator {
    public static void main(String[] args) {
        //参与运算的第一个数
        int a = Integer.parseInt(args[0]);
        //参与运算的第二个数
        int b = Integer.parseInt(args[1]);
        //参与运算的方法
        String method = args[2];
        
        Calculator calculator = new Calculator();
        
        if ("add".equals(method)) {
            System.out.println(calculator.add(a, b));
        } else if ("sub".equals(method)) {
            System.out.println(calculator.sub(a, b));
        } else {
            System.out.println("没有找到计算方法");
        }
    }

    
    public int add(int a, int b) {
        return a + b;
    }

    
    public int sub(int a, int b) {
        return a - b;
    }


}

假如入我们要实现一个乘法和除法,那我们必须又要增加两个方法,一个乘法和一个除法

假如后面我们又有其他的要求,那是不是得又增加许多方法,那有没有一种比较简单且通用的方法来实现我们需要的功能呢

我们先观察一下Calculator方法中的方法,add,sub以及我们将要实现的乘法和除法,都是接收两个参数,返回一个值 ,因此我们可以考虑封装一个算法接口,将算法封装起来

假如我们实现了一个这样的算法接口

public interface ComputeStrategy {
    
    int doCompute(int p1,int p2);
}

然后实现一个加法计算和一个减法计算策略

public class AddComputeStrategy implements ComputeStrategy {
    @Override
    public int doCompute(int p1, int p2) {
        return p1 + p2;
    }
}

public class SubComputeStrategy implements ComputeStrategy {
    @Override
    public int doCompute(int p1, int p2) {
        return p1 - p2;
    }
}

然后将Calculator类改造一下,引入我们的接口

public class Calculator {
    private ComputeStrategy computeStrategy;

    public static void main(String[] args) {


        //参与运算的第一个数
        int a = Integer.parseInt(args[0]);
        //参与运算的第二个数
        int b = Integer.parseInt(args[1]);
        //参与运算的方法
        String method = args[2];

        Calculator calculator = new Calculator();


        if ("add".equals(method)) {
            //设置加法策略
            ComputeStrategy computeStrategy = new AddComputeStrategy();
            calculator.setComputeStrategy(computeStrategy);
            int result = calculator.doCalculate(a, b);
            System.out.println(result);
        } else if ("sub".equals(method)) {
            //设置减法策略
            ComputeStrategy computeStrategy = new SubComputeStrategy();
            calculator.setComputeStrategy(computeStrategy);
            int result = calculator.doCalculate(a, b);
            System.out.println(result);
        } else {
            System.out.println("没有找到计算方法");
        }
    }

    public void setComputeStrategy(ComputeStrategy computeStrategy) {
        this.computeStrategy = computeStrategy;
    }

    public int doCalculate(int p1, int p2) {
        return computeStrategy.doCompute(p1, p2);
    }

}

这样以后我们要增加其他算法,也就只需要增加实现ComputeStrategy接口的子类就可以了,但是这样如果算法很多,并且复用性又比较低怎么办,不可能为每个策略都去写一个实现类,有可能它就只被用到一次,这样做的意义并不大,这个时候我们可以用匿名实现类来代替,比如我们实现一个两个数相加,再翻倍的算法。

public class Calculator {
    private ComputeStrategy computeStrategy;

    public static void main(String[] args) {


        //参与运算的第一个数
        int a = Integer.parseInt(args[0]);
        //参与运算的第二个数
        int b = Integer.parseInt(args[1]);
        //参与运算的方法
        String method = args[2];

        Calculator calculator = new Calculator();


        if ("add".equals(method)) {
            //设置加法策略
            ComputeStrategy computeStrategy = new AddComputeStrategy();
            calculator.setComputeStrategy(computeStrategy);
            int result = calculator.doCalculate(a, b);
            System.out.println(result);
        } else if ("sub".equals(method)) {
            //设置减法策略
            ComputeStrategy computeStrategy = new SubComputeStrategy();
            calculator.setComputeStrategy(computeStrategy);
            int result = calculator.doCalculate(a, b);
            System.out.println(result);
        } else if ("addAndDouble".equals(method)) {
               //两数相加再翻倍
            calculator.setComputeStrategy(new ComputeStrategy() {
                @Override
                public int doCompute(int p1, int p2) {
                    return (p1 + p2) * 2;
                }
            });
            int result = calculator.doCalculate(a, b);
            System.out.println(result);
        } else {
            System.out.println("没有找到计算方法");
        }
    }

    public void setComputeStrategy(ComputeStrategy computeStrategy) {
        this.computeStrategy = computeStrategy;
    }

    public int doCalculate(int p1, int p2) {
        return computeStrategy.doCompute(p1, p2);
    }


}

重点来看这段代码

calculator.setComputeStrategy(new ComputeStrategy() {
                @Override
                public int doCompute(int p1, int p2) {
                    return (p1 + p2) * 2;
                }
            });

这是Java匿名类的写法,这个类实现了ComputeStrategy接口,实现的算法是两数相加并且把结果翻倍。

那有没有一种简单的方法来表示呢,答案是有的,可以用JDK8新增的Lambda表达式来代替

calculator.setComputeStrategy((p1, p2) -> (p1 + p2) * 2);

可以看到,只需要一行代码就可以代替上面的整个匿名类。
虽然上述Lambda表达式看起来只是将语法做了精简,实际上也是一种思想上的转变,它其实是函数作为了方法的入参,这和面向对象的思想还是有区别的。

Lambda表达式的局限性
局限性一
首先接口必须有且只能有一个抽象方法需要子类去实现的,接口的default修饰的方法,由于不需要子类强制去实现,因此也不算在内

只有这样编译器才能正确的推断出调用的哪个方法以及参数的信息,并且Lambda表达式目前支持接口,不支持抽象类

比如这样一个接口,就无法用Lambda表达式来代替

public interface A {
    void doXX1();

    void doXX2();
}

因为Lambda表达式只能表示一个函数,而A接口两个方法都是需要实现的,如果用Lambda表示无法知道使用哪一个,因此这种情况下是使用不了Lambda表达式来代替匿名实现类的。

从这里也能得到另外一个知识,那就是只要满足这个条件,就可以用Lambda表达式表示

比如我们之前经常写的Runnable

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("run");
    }
};

这种我们就可以用Lambda表达式来表示,该方法没有参数没有返回值,因此我们可以写成

Runnable runnable = () -> System.out.println("run");

()里没有参数表示参数为空
->为Lambda表达式分隔符
System.out.println(“run”)为方法体
局限性二
在Lambda表达式中使用的变量必须为不可变或者是一个既成事实上的 final 变量 ,比如下面这段代码,虽然num没有用final修饰,但是也没有二次赋值,因此可以认为它是final的,也就能在Lambda表达式中使用

int num = 2;
calculator.setComputeStrategy((p1, p2) -> (p1 + p2) * num);

但是如果我们再对其赋值一次,如下面这段代码,那么就会编译不通过,因为num二次赋值意味着不再是final的。

int num = 2;
num = 3;
calculator.setComputeStrategy((p1, p2) -> (p1 + p2) * num);
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/760326.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号