庆哥教你如何使用Java lambda表达式

编码之外

共 2999字,需浏览 6分钟

 · 2021-07-14

在Java8中有一个很关键的特性叫做lambda表达式,这个是在后续我们经常要使用的,所以一定要掌握,对于lambda表达式来说,必须是函数式接口接口中有且仅有一个方法声明)才行,接下来我们一步步来看!


首先需要清楚lambda表达式解决的问题:

匿名内部类的代码冗余,使其变得简洁

接下来我们看看lambda表达式如何使用?

lambda表达式怎么写

先看一段代码:

interface OneImpl{
   public void hello();
}

很简单,这里就是定义了一个简单的接口,一个最普通的接口,接下来看怎么用:

new OneImpl() {
 @Override
 public void hello() {
   System.out.println("hello");
}
}.hello();

要注意这里我使用的是匿名内部类的形式,当然你最熟悉的应该是这样:

 OneImpl one = new OneImpl() {
           @Override
           public void hello() {
               System.out.println("hello");
          }
      };
       one.hello();

接下来我们看下使用lambda表达式是怎样的:

OneImpl two = () -> {
           System.out.println("hello");
      };
       two.hello();

是不是简洁很多,不过看到这里是不是有点懵?这样的写法着实有点不懂啊,没关系,一起来看:

注意看区别,这里红框内的都是一样的,不同的是什么呢?是不是这些:

也就是我们常规的匿名内部类的形式被以下的写法给代替了:

发现没,就是这个:

()->{}

然后这个大括号里面可以写一些执行逻辑比如:

() -> {System.out.println("hello");}; 

所以,简单来说,一个小括号,一个右箭头,一个大括号,这就是lambda表达式啊,不过这里要注意了,这是lambda最基本的表达形式,因为小括号和大括号里面都可能是有内容的,比如上面的例子,大括号里面有个输出语句:

System.out.println("hello lambda");

那小括号里面呢?是啥?可能有人猜到了,就是方法参数,下面来看个例子:

interface OneImpl{
   public String hello(String s);
}

这一次,我们的接口中,声明的方法是带有参数和返回值的,这个时候再看lambda的形式:

发现没,此时这里的小括号里面含有与方法声明相同的参数了。而且这里还可以简单的写成这样:

什么意思呢?就是lambda表达式这里的小括号里面的参数,你可以随便写一个,而且不用指定类型,其会自动帮你进行类型推断,再看一个例子:

然后看结果:

OK,以上就是lambda表达式的简单用法了,我相信你已经对它不再那么陌生了,然后我们接着往下看!


函数式接口

这是什么?函数式接口?是不是会觉得有一点陌生呢?


首先,我们再回顾下lambda表达式的基本结构:

()->{}

这里需要注意了:

⚠️要想使用lambda表达式,必须是函数式接口才行

什么意思呢?我们看之前定义的这个接口:

interface OneImpl{
   public String hello(String s,int i);
}

好像没什么特殊的吧,不就是一个普通的接口嘛?如果非要说出来一点特殊性,是不是就是:


只有一个方法声明


好像没啥了,不过这就是重点了,什么是函数式接口啊,首先,它一定是一个接口,其次最重要的一点:

❕函数式接口有且仅有一个方法声明

你要注意了,我这里说的是方法声明,也就是只有声明没有实现,只有方法头,没有方法体!


那么这样的一个接口就称作是函数式接口,就可以使用lambda表达式了!也就是说,要想使用lambda表达式,必须是函数式接口才行,那为了满足这一点,确保对于某些接口来说你可以使用lambda表达式,那么在Java8中就增加了一个独有的注解:

怎么用呢?简单:

这样一来,你这个接口就是函数式接口了,然后我们测试下:

报错了,为啥?你这有函数式接口注解,说明这个接口是一个函数式接口,那只能有一个方法声明,所以报错了!


那我们把这个注解去掉:

但是你就不能用lambda表达式了!


再举一个我们常见的线程的例子:

new Thread(new Runnable() {
           @Override
           public void run() {
               System.out.println("开启一个线程");
          }
      }).start();

我们看下这个Runnable接口:

发现没,是个函数式接口,所以我们就可以这样写:

 new Thread(()->{
           System.out.println("开启一个线程");
      }).start();

现在你应该知道什么是函数式接口了吧!

注意事项

以上我们大致清楚了lambda表达式的基本用法,也清楚了函数式接口的定义,那么其中还有一些需要我们格外注意的事项⚠️


首先让我们回顾下这句话:


函数式接口允许有一个且仅有一个方法声明

然后我们看下这段代码:

看到没,这里是允许你定义一个默认的方法的,这个是从Java8开始增加的特性,再看一个:

明白呗,就是允许你定义多个默认方法,然后还有如下的一个例子:

这说明在函数式接口中除了可以定义多个默认方法之外还可以定义多个static静态方法,那如何使用:

ok,上图描述还是很直观的!


那么,你学会了吗?记得点赞哦!

浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报