个人博客:javalover.cc
前言大家好啊,我是汤圆,今天给大家带来的是《Java8中的Lambda表达式》,希望对大家有帮助,谢谢
文章纯属原创,个人总结难免有差错,如果有,麻烦在评论区回复或后台私信,谢啦
简介Lambda表达式是一个可传递的代码块,可以在以后执行一次或多次;
下面贴个对比代码:
// Java8之前:旧的写法 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("old run"); } }; Thread t = new Thread(runnable); // Java8之后:新的写法 Runnable runnable1 = ()->{ System.out.println("lambda run"); }; Thread t1 = new Thread(runnable1);可以看到,有了lambda,代码变得简洁多了
你可以把lambda当作一个语法糖
下面让我们一起来探索lambda的美好世界吧
目录下面列出本文的目录
lambda的语法
为啥引入lambda
什么是函数式接口
什么是行为参数化
手写一个函数式接口
常用的函数式接口
什么是方法引用
什么是构造引用
lambda的组合操作
正文 1. lambda的语法下面分别说下语法中的三个组成部分
参数: ( Dog dog )
参数类型可省略(当编译器可以自动推导时),比如Comparator<String> comparatorTest = (a, b)->a.length()-b.length();,可以推导出a,b都为String
当参数类型可省略,且只有一个参数时,括弧也可以省略(但是个人习惯保留)
符号: ->
主体:{ System.out.println("javalover"); }
如果是一条语句,则需要加大括号和分号{;}(比如上图所示)
如果是一个表达式,则直接写,啥也不加(比如a.length()- b.length())
2. 为啥引入lambda为了简化代码
因为Java是面向对象语言,所以在lambda出现之前,我们需要先构造一个对象,然后在对象的方法中实现具体的内容,再把构造的对象传递给某个对象或方法
但是有了lambda以后,我们可以直接将代码块传递给对象或方法
现在再回头看下开头的例子
可以看到,用了lambda表达式后,少了很多模板代码,只剩下一个代码块(最核心的部分)
3. 什么是函数式接口就是只定义了一个抽象方法的接口
正例:有多个默认方法,但是如果只有一个抽象方法,那它就是函数式接口,示例代码如下
@FunctionalInterface public interface FunctionInterfaceDemo { void abstractFun(); default void fun1(){ System.out.println("fun1"); } default void fun2(){ System.out.println("fun2"); } }这里的注解@FunctionalInterface可以省略,但是建议加上,就是为了告诉编译器,这是一个函数式接口,此时如果该接口有多个抽象方法,那么编译器就会报错
反例:比如A extends B,A和B各有一个抽象方法,那么A就不是函数式接口,示例代码如下
// 编译器会报错,Multiple non-overriding abstract methods found in XXX @FunctionalInterface public interface NoFunctionInterfaceDemo extends FunctionInterfaceDemo{ void abstractFun2(); }上面的父接口FunctionInterfaceDemo中已经有了一个抽象方法,此时NoFunctionInterfaceDemo又定义了一个抽象方法,结果编译器就提示了:存在多个抽象方法
在Java8之前,其实我们已经接触过函数式接口
比如Runnable 和 Comparable
只是没有注解@FunctionalInterface。
那这个函数式接口要怎么用呢?
配合lambda食用,效果最佳(就是把lambda传递给函数式接口),示例代码如下:
new Thread(() -> System.out.println("run")).start();其中用到的函数式接口是Runnable
4. 什么是行为参数化就是把行为定义成参数,行为就是函数式接口
类似泛型中的类型参数化<T>,类型参数化是把类型定义成参数
行为参数化,通俗点来说:
就是用函数式接口做形参
然后传入接口的各种实现内容(即lambda表达式)作为实参
最后在lambda内实现各种行为(好像又回到多态的那一节了?这也是为啥多态是Java的三大特性的原因之一,应用太广泛了)
这样来看的话,行为参数化和设计模式中的策略模式有点像了(后面章节会分别讲常用的几种设计模式)
下面我们手写一个函数式接口来加深理解吧
5. 手写一个函数式接口下面我们循序渐进,先从简单的需求开始