JDK8新特性之Lambda表达式、函数式接口


在这里插入图片描述

1. 什么是Lambda表达式 ❓

Lambda表达式时JDK8的一个重要的特性,它使用一个清晰简介的表达式来表达一个接口,同时Lambda表达式也简化了对接和以及数组数据的遍历、过滤和提取等操作。

⭐️1.1入门🚪

Lambda表达式可以简化匿名内部类
如果匿名内部类的实现非常简单,例如只包含一个抽象方法的接口,那么匿名内部类的语法仍然显得比较冗余。所以JDK8增加了一个特性Lambda表达式,但是这种表达式只针对有一个抽象方法的接口实现,以简洁的的表达式形式实现接口的功能来作为方法参数

🔥1.2Lambda语法

在这里插入图片描述
([数据类型,参数名.......])->{表达式主体}

  • ([数据类型,参数名.......]):指的是 向表达式主体传递接口方法需要的参数。多个参数中间用 , 隔开。参数的数据类型可以省略,后面的表达式主题会自动进行校对和匹配。
    • 如果只有一个参数,则可以省略括号
  • ->:表示Lambda表达式箭牌,用来指定参数数据指向,不能省略,必须是英文横线和大于号书写
  • { 表达式主体}:本质就是接口中抽象方法的具体实现
    • 如果表达式主题只有一条语句,那么可以省略包含主体的大括号
    • 在有返回值时,如果只有一条return语句,也可以省略return关键字
👊1.3Lambda表达式实操

//定义接口
interface Animal{
    void shout();
}
class A implements Animal{

    @Override
    public void shout() {
        System.out.println("最正常的方式");
    }
}
class test{
    public static void main(String[] args) {
        String name="一键三连";

        //使用内名内部类作为参数传递给animalshout方法
        animalshout(new Animal() {
            @Override
            public void shout() {
                System.out.println("匿名内部类都会"+name);
            }
        });

        //使用Lambda表达式
        animalshout(()-> System.out.println("Lambda表达式也会"+name));

        //最正常的方式
        A a=new A();
        animalshout(a);


    }
    public static void animalshout(Animal an){

        an.shout();
    }
}

运行结果:在这里插入图片描述
上面的代码中调用animalshout方法时需要一个Animal接口类型的参数,遇到这种情况我们有三种选择

  1. 实现这个接口,传入这个接口实现类的对象。也就是我们上面定义的最正常的方式。但是这种方式有个弊端,不能访问name属性,因为name属性是main方法的局部变量。而且写法明显也比较麻烦
  2. 使用匿名内部类,可以看到这种方式访问了局部变量name,而局部变量并没有使用final修饰,程序也没有报错。
    这是JDK8开始有的新特性,允许在局部内部类、匿名内部类中访问非final修饰的局部变量,而在JDK8之前,局部变量前必须加final修饰符,否则程序编译出错
  3. 使用Lambda表达式,可以看出使用Lambda表达式写出的代码更加简洁和清晰。

2.函数式接口

在这里插入图片描述

2.1什么是函数式接口❓

函数式接口是指有且仅有一个抽象方法的接口,Lambda表达式就是Java中的函数式编程的体现,只有确保接口中有且仅有一个抽象方法,Lambda表达式才能顺利的推导出所实现的这个接口中的方法

🔔2.2@FunctionalInterface注解

在JDK8中专门为函数时接口引入了一个@FunctionalInterface注解,该注解只是显示的标注了接口是一个函数式接口,并强制编辑器进行更严格的检查,如果不是函数式接口,那么编译器就会报错,对程序运行并没有实质上的影响。类似于@overwrite注解

📢2.3方法引用和构造器引用

Lambda表达式的主体只有一条语句时,程序不仅可以省略大括号,还可以通过英文 “::”的语法格式来引用方法和构造器(构造方法)。

🔍📚2.3.1Lambda表达式对普通方法和构造方法的引用形式
种类Lambda表达式示例对应的引用示例
类名引用普通方法(x,y,…)->对象名 x.类普通方法名(y,…)类名::类普通方法名
类名引用静态方法(x,y,…)->类名.类静态方法名(x,y,…)类名::类静态方法名
对象名引用方法(x,y,…)->对象名.实例方法名(x,y,…)对象名::实例方法名
构造器引用(x,y,…)->new类名(x,y,…)类名::new
📕2.3.1.1类名引用静态方法

//定义一个函数式接口
@FunctionalInterface
interface Calcable{
    int calc(int num);
}
//定义一个类且包含静态方法
class Math{
    //静态方法
    public static int abs(int num){
        if(num<0){
            return -num;
        }else {
            return num;
        }
    }
}
//定义测试类
class test{
    private static void printAbs(int num,Calcable calcable){
        System.out.println(calcable.calc(num));
    }

    public static void main(String[] args) {
        //使用lambda表达式
        printAbs(-100,n->Math.abs(n));
        //使用方法引用方式
        printAbs(-200,Math::abs);

    }
}

结果
在这里插入图片描述

可以看出使用类名引用静态方法的方式更加简洁

其实不论是Lambda表达式还是方法引用 都是帮助我们写的代码更加清晰和简洁,设想一下如果我们没有掌握这两种方法,那我们要完成上面代码的调用应该怎么办?

📗2.3.1.2 不使用Lambda表达式和类名引用静态方法

//定义一个函数式接口
@FunctionalInterface
interface Calcable{
    int calc(int num);
}
//定义一个类实现接口并重写方法
class Math implements Calcable{

    @Override
    public int calc(int num) {
        if(num<0){
            return -num;
        }else {
            return num;
        }
    }
}
//定义测试类
class test{
    private static void printAbs(int num,Calcable calcable){
        System.out.println(calcable.calc(num));
    }

    public static void main(String[] args) {
        Math math=new Math();
        printAbs(50000,math);

    }
}

可以看出如果不使用JDK8给我们的新特性的话,我们就需要写一个接口的实现类,并且实现这个方法,然后在调用的时候,还需要实例化实现类。
通过对比可以更加理解新特性带来的方式的实现方法更为简洁。

📘2.3.1.3对象名引用方法

代码示例


//定义一个函数式接口
@FunctionalInterface
interface Calcable{
    String calc(int num);
}
class Math{
    //静态方法
    public  String abs(int num){
        if(num<0){
            return "是负数";
        }else {
            return "不是负数";
        }
    }
}
//定义测试类
class test{
    private static void printAbs(int num,Calcable calcable){
        System.out.println(calcable.calc(num));
    }

    public static void main(String[] args) {
        Math ma=new Math();
        //使用lambda表达式
        printAbs(-100,n->ma.abs(n));
        //使用方法引用方式
        printAbs(-200,ma::abs);

    }
}

运行结果在这里插入图片描述
还是方法引用更加简洁

📙2.3.1.4构造器引用方法

看代码示例


//定义一个函数式接口
@FunctionalInterface
interface PersonFace{
    Person build(String name);
}
//定义Person类,并添加构造方法
class Person{
    String name;
    public Person(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
//定义测试类
class test{
    private static void printName(String name,PersonFace personFace){
        System.out.println(personFace.build(name).getName());
    }

    public static void main(String[] args) {
        //使用lambda表达式
       printName("使用lambda表达式会三连",n->new Person(n));
        //使用方法引用方式
       printName("使用方法引用方式会三连",Person::new);

    }
}

运行结果
在这里插入图片描述

📒2.3.1.5 类名引用普通方法

看代码示例



//定义一个函数式接口
@FunctionalInterface
interface Printable {
    void print(StringU stringU, String str);
}

//定义Person类,并添加构造方法
class StringU {
    public void printUpperCase(String str) {
        System.out.println(str.toUpperCase());
    }
}

//定义测试类
class test1 {
    private static void printUpper(StringU stringUtils, String text,Printable printable) {
       printable.print(stringUtils,text);
    }

    public static void main(String[] args) {
        //使用lambda表达式
        printUpper(new StringU(),"Java",(object,t)->object.printUpperCase(t));
        //使用方法引用方式
        printUpper(new StringU(),"Java",StringU::printUpperCase);

    }
}

运行结果在这里插入图片描述
在这里插入图片描述

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

圆○

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值