Lambda表达式

Lambda表达式

  • 概述
    Lambda表达式可以看做一个可以重写函数式接口抽象方法的实现类对象。

  • 使用前提

    • .必须是接口,并且接口中有且仅有一个抽象方法。(函数式接口)
    • .有上下文环境,才能推导出Lambda对应的接口"实现类对象"。
      1. 根据局部变量的赋值推导Lambda对应的接口:Runnable r = () -> System.out.println(“Lambda表达式”);
      2. 根据调用方法的参数推导Lambda对应的接口:new Thread(() -> System.out.println(“Lambda表达式”)).start();
  • Lambda的标准格式

    • 格式(形式参数) -> {代码块}
      • 形式参数:根据函数式接口抽象方法的参数而定,有多个参数用逗号隔开;没有参数就留空
      • ->:固定写法,代表指向动作。
      • 代码块:具体要做的事情,类似匿名内部类方法体内容。(抽象方法的方法体具体实现)
  • 启动一个线程,用实现Runnable接口、匿名内部类和Lambda表达式进行对比

    class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("Runnable线程启动了");
        }
    }
    public class Demo {
        public static void main(String[] args) {
            //实现Runnable接口,启动新线程
            MyRunnable mr = new MyRunnable();
            Thread t1 = new Thread(mr);
            t1.start();
            //匿名内部类,启动新线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("匿名内部类线程启动了");
                }
            }).start();
            //Lambda表达式,启动新线程
            new Thread(() -> {
                System.out.println("Lambda线程启动了");
            }).start();
        }
    }
    ---*---
    输出结果:
    Runnable线程启动了
    匿名内部类线程启动了
    Lambda线程启动了
    

    Lambda表达式 ( ) -> { },和匿名内部类对比可以将:

    • ( ):看作抽象方法形式参数为空
    • ->:箭头指向方法体
    • { }:看作方法体中的内容

练习

  • 函数式接口,无参无返回值抽象方法

    //有且仅有一个抽象方法的接口
    interface A{
        void eat();
    }
    
    class B implements A{
        @Override
        public void stude() {
            System.out.println("好好学习,天天向上");
        }
    }
    public class Demo {
        public static void main(String[] args) {
    	    //创建实现类
    	    B b = new B();
    	    show(b);
    	    //匿名内部类
    	    show(new A() {
    	        @Override
    	        public void stude() {
    	            System.out.println("好好学习,天天向上");
    	        }
    	    });
    	    //Lambda
    	    show(()->{
    	        System.out.println("好好学习,天天向上");
    	    });
        }
        //参数是A接口的测试方法
        public static void show(A a){
            a.eat();
        }
    }
    ---*---
    输出结果:
    好好学习,天天向上
    好好学习,天天向上
    好好学习,天天向上
    
  • 函数式接口,带参无返回值抽象方法

    //接口,一个带参抽象方法
    interface A{
        void stude(String s);
    }
    
    public class Demo {
        public static void main(String[] args) {
    	    //匿名内部类
    	    show(new A() {
    	        @Override
    	        public void stude(String s) {
    	            System.out.println(s);
    	            System.out.println("好好学习,天天向上");
    	        }
    	    });
    	
    	    //Lambda
    	    show((String s)->{
    	        System.out.println(s);
    	        System.out.println("好好学习,天天向上");
    	    });
        }
        //调用接口的测试方法
        public static void show(A a){
            a.stude("圆圆");
        }
    }
    ---*---
    输出结果:
    圆圆
    好好学习,天天向上
    圆圆
    好好学习,天天向上
    
  • 函数式接口,带参有返回值抽象方法

    //函数接口,带参有返回值
    interface A{
        int add(int x, int y);
    }
    
    public class Demo {
        public static void main(String[] args) {
            //Lambda
            test((int x, int y) ->{
                return x+y;
            });
        }
        //调用接口的测试方法
        public static void test(A a){
            int add = a.add(10, 20);
            System.out.println(add);
        }
    }
    ---*---
    输出结果:
    30
    

Lambda省略模式

  • 概述:

    • 1.参数类型可以省略。如有多个参数只能都省略或都不省略。
    • 2.参数有且仅有一个,圆括号可以省略。
    • 3.如果代码块语句只有一条,可以省略大括号和分号;有返回值还要省略return。
  • ①省略参数类型

    //函数式接口
    public interface Inter {
        int est(int x, int y);
    }
    
    public class Demo {
        public static void main(String[] args) {
            //Lambda
            show((int x,int y) -> {
                return x+y;
            });
            //ambda省略参数类型
            show((x,y) -> {
                return x+y;
            });
        }
        public static void show(Inter in){
            int est = in.est(10, 20);
            System.out.println(est);
        }
    }
    ---*---
    输出结果:
    30
    30
    

    注意:有多个参数的情况下,只能都省略或者都不省略。

  • ②如果只有一个参数,小括号可以省略。

    //函数式接口
    public interface Inter {
        void est(int x);
    }
    
    public class Demo {
        public static void main(String[] args) {
            //Lambda
            show((x) ->{
                System.out.println(x);
            });
            //Lambda,省略圆括号
            show(x -> {
                System.out.println(x);
            });
        }
        public static void show(Inter in){
             in.est(100);
        }
    }
    ---*---
    输出结果:
    100
    100
    
  • ③如果代码块的语句只有一条,可以省略花括号和分号

    //函数式接口
    public interface Inter {
        void est(int x);
    }
    
    public class Demo {
        public static void main(String[] args) {
            //Lambda
            show(x ->{
                System.out.println(x);
            });
            //Lambda,省略大括号
            show(x -> System.out.println(x));
        }
        public static void show(Inter in){
             in.est(100);
        }
    }
    ---*---
    输出结果:
    100
    100
    

    注意:Lambda表达式在只有一条语句,省略调花括号和分号的情况下。如果该抽象方法有返回值,还需要省略 return。

Lambda表达式和匿名内部类的区别

  • 所需类型不同

    • 匿名内部类:可以是接口、抽象类和具体类

    • Lambda表达式:只能是接口

      //函数式接口
      public interface S1 {
          void inter();
      }
      //抽象类
      abstract class S2{
          abstract void abs();
      }
      //具体类
      class S3{
          void cla(){}
      }
      
      public class Demo {
          //测试方法,参数为接口,抽象类和具体类对象
          public static void show1(S1 s1){
              s1.inter();
          }
          public static void show2(S2 s2){
              s2.abs();
          }
          public static void show3(S3 S3){
              S3.cla();
          }
          //mian方法
          public static void main(String[] args) {
              //传入匿名内部类对象
              show1(new S1() {
                  @Override
                  public void inter() {
                      System.out.println("inner-s1");
                  }
              });
              show2(new S2() {
                  @Override
                  void abs() {
                      System.out.println("inner-s2");
                  }
              });
              show3(new S3(){
                  @Override
                  void cla() {
                      System.out.println("inner-s3");
                  }
              });
      
              //传入Lambda表达式推导的实现类对象
              show1(() -> {
                  System.out.println("Lambda-s1");
              });
      //        show2(() -> {});//报错,Lambda转换的目标类型必须是接口
      //        show3(() -> {});//报错,Lambda转换的目标类型必须是接口
          }
      }
      ---*---
      输出结果:
      inner-s1
      inner-s2
      inner-s3
      Lambda-s1
      
  • 使用限制不同

    • 接口中有且仅有一个抽象方法,可以使用Lambda表达式或匿名内部类
    • 接口中有多个抽象方法,只能使用匿名内部类。
      //有多个抽象方法的接口
      public interface S1 {
          void inter();
          void inter1();
      }
      
      public class Demo {
          //测试方法,参数为接口
          public static void show1(S1 s1){
              s1.inter();
          }
          //main
          public static void main(String[] args) {
              //匿名内部类
              show1(new S1() {
                  @Override
                  public void inter() {
                      System.out.println("inner-s1");
                  }
                  @Override
                  public void inter1() {
      
                  }
              });
              //Lambda
      //        show1(() -> {});//报错,存在多个抽象方法
          }
      }
      
  • 实现原理不同

    • 匿名内部类:编译后,产生一个单独的.class字节码文件
    • Lambda表达式:编译后,不产生单独的.class字节码文件。对应的字节码会在运行时动态生成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值