zoukankan      html  css  js  c++  java
  • 快速掌握Java中Lambda表达式的用法

    Lambda表达式的作用:

      Lambda表达式的作用就是简化代码开发,让代码看起来更加简介。它是用来简化匿名内部类的。但是并不是所有的匿名内部类都能用Lambda表达式简化,Lambda表达式是有使用前提的。

    Lambda表达式的使用前提:

      1、用Lambda表达式简化的这个匿名内部类必须是某一个接口的实现类,且这个实现的接口中有且只有一个抽象方法;因为只有这样,Lambda才能够根据接口中的上下文(代码)来推断出你简化的地方是什么内容,下面就来实际演示一下。(注:有且只有一个抽象方法的接口称为“函数式接口”)

      2、使用Lambda表达式的地方必须具有上下文推断,就是在使用Lambda表达式的地方知道能够通过代码上下文推断出所需要的信息,因为Lambda表达式简化匿名内部类是不会写出匿名内部类实现所实现的接口,所以需要在能够推测出接口的地方使用(有点抽象,可以通过下面的案例来理解)。

    Lambda表达式的格式:

      Lambda表达式主要由三部分构成:()->{ }

        1、开头小括号开始 ( ) :小括号中填写的是重写接口中的方法时,方法的参数。若方法无参数,则小括号空着,若有多个参数,则参数间用逗号隔开(与普通Java方法相同)

        2、中间一个箭头 ->:可以理解为将参数传入到方法体中;

        3、末尾一个大括号{ }:大括号中的内容就是方法体,也就是方法的逻辑代码;

      当然,上面的结构是标准结构,但却不是绝对的,在某些情况下,部分内容可以省略,在下面的案例中将进行详细讲解。

    Lambda使用案例:

      案例一:Lambda表达式简化匿名内部类,重写无参数无返回值方法

      首先,我们创建一个接口,用来测试Lambda表达式。通过Lambda表达式的使用前提可知,这个接口应当有且只有一个抽象方法。接口名字叫Test,方法叫display():

    1 public interface Test {
    2     
    3     public abstract void display();
    4 
    5 }

      然后,我们创建一个类,这个类中有一个方法useDisplay(Test t),它唯一的参数就是上面定义的接口Test。我们知道,当要调用这个方法时,应当传入一个Test接口的实现类,方法代码如下:

    1 public static void useDisplay(Test t) {
    2     //方法的内容就是调用接口中的display方法
    3     t.display();
    4 }

      接下来,我们调用这个方法,分别采用匿名内部类以及Lambda表达式两种方式,以此来进行对比:

     1 //调用方法,接口参数使用匿名内部类当场实现
     2 useDisplay(
     3     new Test() {
     4         //重写接口中的方法,输出一句话
     5         @Override
     6         public void display() {
     7             System.out.println("Lambda表达式案例一");
     8         }
     9     }
    10 );

      上面的代码调用了useDisplay(Test t)方法,并在括号中使用匿名内部类实现了Test接口以及重写了Test的方法,将匿名内部类作为参数传递。这是匿名内部类的方式,那下面看看Lambda表达式时怎么去写的:

    1 useDisplay(
    2     //使用Lambda实现
    3     ()->{
    4         System.out.println("Lambda表达式案例一");
    5     }
    6 );

      可以看到,代码明显精简了许多,我们来仔细看看究竟做了哪些改变:我们省略new,也省略了接口的名字,直接重写接口中的方法。为什么可以这么做呢,这就关系到我们之前所说的Lambda使用前提2:使用Lambda表达式的地方必须具有上下文推断;Lambda知道useDisplay的参数是Test接口,所有Lambda知道这里应该实现的接口就是Test,不可能是其他的了,因此可以省略接口名。接下来省略了方法的public、返回值类型、方法名,这些Lambda也可以推断出来,因为已经确定了是Test接口,那自然也知道了这个接口中的方法display()的信息,所以统统可以省略,这也是Lambda表达式使用前提1的原因。

      然而,上面的Lambda表达式只是标准格式,它还能够继续简化,上面的表达式简化后的如下:

    1 useDisplay(  ()->System.out.println("Lambda表达式案例一") /*此处原本有分号*/ );

      可以看到,上面的Lambda表达式相对于之前,省略了大括号以及末尾的分号。只有在Lambda表达式的方法体,也就是大括号中只有一条语句时,才能够省略大括号,同时也要省略分号,两者要么一起省略,要么都不省略。

      案例二:Lambda表达式简化匿名内部类,重写有参有返回值方法

      同样是定义一个接口Calculator,里面只有一个抽象方法add(),计算两个整数的和:

    1 public interface Calculator {
    2     
    3     public abstract int add(int a,int b);
    4 
    5 }

      与上一个案例类似的结构,在另一个类中定义一个方法invokeAdd,方法的内容就是调用接口中的add方法,得到两个整数的和并输出:

    1 public static void invokeAdd(int a,int b,Calculator cal) {
    2     System.out.println(cal.add(a, b));
    3 }

      首先还是和第一个案例一样,我们使用匿名内部类的方式调用这个方法(这次我把代码写的紧凑一些,上一个案例代码都拉的很开,方便查看):

    1 invokeAdd(10, 20, new Calculator() {
    2     @Override
    3     public int add(int a, int b) {
    4         return a+b;
    5     }
    6 });

      上面代码很简单,传入两个要相加的整数10和20,以及一个匿名内部类对象实现,实现Calculator接口,重写接口中add方法,求两个整数的和。下面来看看Lambda表达式怎么写上面这个代码:

    1 //使用Lambda表达式的方式代替匿名内部类实现
    2 invokeAdd(10, 20, (int a,int b)->{
    3     return a+b;
    4 });

      还是来看看改变了哪些内容:首先,这是比较标准的写法,与案例一相同,省略了接口,直接重写接口中的方法,然后省略了方法的名字类型等,只留下一个大括号,里面包含方法的参数,后面跟着一个箭头,指向了方法体,而方法体则未改变。但是,这并不是最简略的写法,看下面这种更加简洁的写法:

    1 //上Lambda表达式的简化
    2 invokeAdd(10, 20, (a,b) -> a+b );

      可以看到,这时已经简化到只剩一句代码了,我们来仔细看看简化了哪些内容:首先,填写方法参数的小括号中,参数的类型省略了,还是和上面一样的原因,既然Lambda表达式已经知道了你实现的接口,就知道了接口中那唯一的方法,也就知道了方法中参数的类型,所以即使你省略,Lambda也能够根据上下文推测出来;其次,因为方法体中只有一句代码,所以可以省略大括号以及方法体中语句末尾的分号;除此之外,这是一个有返回值的方法,在方法体中只有一句代码的情况下,连return这个关键字都能省略。(注意:大括号,逗号,return关键字,要么一起省略,要么都不省略。

     

      最后再说一个可以简化Lambda表达式的情况,就是当接口中的方法只有一个参数时,连填写参数的小括号都可以省略,这里就不演示了。

  • 相关阅读:
    ADB命令大全
    Backup your Android without root or custom recovery -- adb backup
    Content portal for Pocketables Tasker articles
    Is there a way to detect if call is in progress? Phone Event
    Tasker to proximity screen off
    Tasker to detect application running in background
    Tasker to create toggle widget for ES ftp service -- Send Intent
    Tasker to proximity screen on
    Tasker to answer incoming call by pressing power button
    Tasker to stop Poweramp control for the headset while there is an incoming SMS
  • 原文地址:https://www.cnblogs.com/tuyang1129/p/10758748.html
Copyright © 2011-2022 走看看