之前看过一些java8的特性,看过又忘了,自己总结一下,以后忘了再来翻翻!有错欢迎指出!
lambda表达式
首先lambda表达式的用法主要就是为了优化函数式接口,那么至少函数式接口的概念得搞懂吧!
函数式接口
函数式接口就是有且只有一个抽象方法的接口就叫函数式接口,可以有其他方法,如静态方法,默认方法,私有方法等;
如果要写函数式接口,可以打个@FunctionalInterface可以提醒你是否是正确的函数式接口,如果错了,idea编译器会直接提醒你。
函数式接口浓缩成lambda表达式
直接搬图!
然后就是lambda表达式的入门及应用了,网上的很多教程都跳的有点前,没有一步一步理解,看了on java 8总算理清思路了。
lambda表达式从0入门
//首先我们自己写个函数式接口
@FunctionalInterface
interface IStudentService{
String toDo(String str);
}
/*然后我们写一个lamdba表达式,
就会自动编译为实现了函数式接口的抽象方法,
因为有且只有一个抽象方法,所以就是直接实现了toDo方法
同时在接收的同时也返回了这个对象
这里只做方法的实现,所以h只是个参数,
我之前还一直懵逼说这个值怎么塞进去,真傻!
重要的事情说三遍
lamdba表达式只是实现抽象方法的方法体!
lamdba表达式只是实现抽象方法的方法体!
lamdba表达式只是实现抽象方法的方法体!
*/
public class lambdaTest {
public static void main(String[] args) {
IStudentService studentService=h->"我在正在"+h;
/*可以理解为
IStudentService studentService=new StudentServiceImpl();
也就是有个子类实现了抽象方法,让接口来接收,这个有学过mvc的同学就懂了!*/
System.out.println(studentService.toDo("学lambda表达式"));
}
}
所以当我们使用studentService.toDo(String str)方法时,就会照着表达式的方法去做,所以输出结果就是
我在正在学lambda表达式
lambda表达式的组成与写法
h -> doString;
第一个组成部分是参数,分为几种情况
参数个数 | 写法 |
---|---|
0 | 直接写个 (),必须写 |
1 | 可以写()也可以不写,如 str ,或(str),像我上面的例子就是直接不写括号 |
2及以上 | 如果是2个,或者2个以上,就必须用括号括起来,如(str1,str2) |
第二个组成部分是->就是指向,固定的符号
第三个组成部分就是方法体了,也是有多种情况
首先是只有一行的情况下,可以不写大括号直接结束,有返回值自动return;
如果只有一行的情况下,写了return,就必须用大括号括起来。
两行及以上,则必须要用大括号括起来!而且有返回值的情况下,必须写return。
public class lambdaTest {
public static void main(String[] args) {
IStudentService studentService=h->{
System.out.println("hi");
return "我在正在"+h;
};
System.out.println(studentService.toDo("学lambda表达式"));
}
}
输出的结果为
hi
我在正在学lambda表达式
这里需要注意的几点
- 多行有返回值必须在最后一行return;单行不用写也不能写return;
- 写了大括号的情况下,后面要写个分号‘’ ; ‘’示意这个lambda表达式结束。
- 多行的方法体写法与正常的书写方法一致。
Runnable结合lambda表达式
Runnable接口就是一个函数式接口
所以我们同样可以用lambda表达式来实现线程的run方法,不用特意用匿名内部类来重写run方法那么长的代码块。
所以我们本来是写
new Thread(new Runnable() {
@Override
public void run() {
do something...
}
}).start();
就可以转换为
new Thread(()->do something...).start();
是不是省了很多事?这就是lambda表达式的魅力所在!
方法引用 ::
至于那个 “ :: ”方法引用,跟lambda表达式差不多,只是方法不同,他可以直接将一个实现的方法引用过来直接实现那个函数式接口。
class X {
String f() { return "X::f()"; }
}
interface MakeString {
String make();
}
interface TransformX {
String transform(X x);
}
public class UnboundMethodReference {
public static void main(String[] args) {
// MakeString ms = X::f; // [1]
TransformX sp = X::f;
X x = new X();
System.out.println(sp.transform(x)); // [2]
System.out.println(x.f()); // 同等效果 }
}
我自己手打了一下,也发现了一些坑
-
方法的引用不要带括号,像我刚才就错写成X::f()
-
函数式接口无返回值的方法可以接受有返回值方法的引用,里面做了什么操作一样会做,只是变成无返回值,不过最好别这样乱搞,免得出了什么纰漏。
-
函数式接口有返回值的方法不可以接受无返回值方法的引用,编译器会直接报错。
-
函数式接口不能接收抽象方法的引用,必须先实现它,或者说抽象方法不能被引用更贴切些!
-
最后再回忆一下前面说的,方法名不用相同也可以传递引用。
参考博客:
Lambda 表达式有何用处?如何使用?