> 文档中心 > JDK8新特性之Lambda表达式、函数式接口

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

JDK8特性之Lamdba、函数式接口

      • 1. 什么是Lambda表达式
        • ⭐️1.1入门🚪
        • 🔥1.2Lambda语法
        • 👊1.3Lambda表达式实操
      • 2.函数式接口
        • 2.1什么是函数式接口❓
        • 🔔2.2@FunctionalInterface注解
        • 📢2.3方法引用和构造器引用
          • 🔍📚2.3.1Lambda表达式对普通方法和构造方法的引用形式
            • 📕2.3.1.1类名引用静态方法
            • 📗2.3.1.2 不使用Lambda表达式和类名引用静态方法
            • 📘2.3.1.3对象名引用方法
            • 📙2.3.1.4构造器引用方法
            • 📒2.3.1.5 类名引用普通方法

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

1. 什么是Lambda表达式 ❓

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

⭐️1.1入门🚪

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

🔥1.2Lambda语法

JDK8新特性之Lambda表达式、函数式接口
([数据类型,参数名.......])->{表达式主体}

  • ([数据类型,参数名.......]):指的是 向表达式主体传递接口方法需要的参数。多个参数中间用 , 隔开。参数的数据类型可以省略,后面的表达式主题会自动进行校对和匹配。
    • 如果只有一个参数,则可以省略括号
  • ->:表示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();    }}

运行结果:JDK8新特性之Lambda表达式、函数式接口
上面的代码中调用animalshout方法时需要一个Animal接口类型的参数,遇到这种情况我们有三种选择

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

2.函数式接口

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

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
JDK8新特性之Lambda表达式、函数式接口 JDK8新特性之Lambda表达式、函数式接口
📕2.3.1.1类名引用静态方法
//定义一个函数式接口@FunctionalInterfaceinterface 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);    }}

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

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

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

📗2.3.1.2 不使用Lambda表达式和类名引用静态方法
//定义一个函数式接口@FunctionalInterfaceinterface 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对象名引用方法

代码示例

//定义一个函数式接口@FunctionalInterfaceinterface 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);    }}

运行结果JDK8新特性之Lambda表达式、函数式接口
还是方法引用更加简洁

📙2.3.1.4构造器引用方法

看代码示例

//定义一个函数式接口@FunctionalInterfaceinterface 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);    }}

运行结果
JDK8新特性之Lambda表达式、函数式接口

📒2.3.1.5 类名引用普通方法

看代码示例

//定义一个函数式接口@FunctionalInterfaceinterface 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);    }}

运行结果JDK8新特性之Lambda表达式、函数式接口
JDK8新特性之Lambda表达式、函数式接口

51银饰网