前言
Java8新特性-Lambda表达式,好像很酷炫的样子,直接搬运官方文档:
Purpose This tutorial introduces the new lambda expressions included in Java Platform Standard Edition 8 (Java SE 8). Time to Complete Approximately 1 hour Introduction Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection. In addition, new concurrency features improve performance in multicore environments.
所以学习这么酷炫的东西其实只需要大约一个小时就足够了;
介绍里面只有一句重点,其他都是废话:
Lambada表达式: 它们通过使用表达式来提供一种清晰简洁的方式来表示方法接口
然而,我还是不知道方法接口是个什么东西,直到我看完了文档,才发现这句也是废话;因为这个得懂了Lambada表达式是什么了才能理解这句话;
匿名内部类
学习Lambda表达式之前,先感受下匿名内部类使用:
/**创建一个Runnable接口的实例*/ Runnable runnable = new Runnable() { @Override public void run() { // } }; /**如果是创建一个线程可以这样*/ Thread thread = new Thread(new Runnable() { @Override public void run() { // } });
以上代码创建一个线程,我们知道得到一个接口实例只能实例化其实现类,但是这里我并没有创建一个具体的实现类,因为我不需要再次使用它;而是使用了匿名类代替,相比之下这样的做法使得代码更紧凑简洁;
函数式接口 和 Lambda表达式语法
函数式接口:
Java8 将只有一个抽象方法的接口叫做 函数式接口
@FunctionalInterface注解只是显示表示这个接口是函数式接口,在定义函数式接口时就会检查是否符合函数式接口规范,Java自己实现的函数式接口都有这个注解,所以你懂的,规范是好事情
Lambda表达式语法(三部分组成):
参数列表 -> 方法体
比如: (int x)-> {System.out.println(x);}
实现函数式接口并使用Lambda表达式:
@FunctionalInterface interface A{ void opration(); } class B { void realOpration(A fi){ fi.opration(); } } public class Tests { @Test public void test(){ /**创建接口A的实例*/ A a = ()-> System.out.println("this is A "); a.opration(); /**再来试试这个支持Lambda表达式的方法*/ B b = new B(); b.realOpration(()-> System.out.println("this is A")); } }
所以Lambda表达式是什么?
看了上面简单的demo,所以Lambda表达式干了什么事情,System.out.println("this is A ") 就是函数式接口的匿名实现,只是用了一种特殊的非常简洁的形式来表示而已,那么这种表示方法就是Lambda表达式;为什么这么简洁,因为它不仅是匿名类,还特么把方法都匿名了,因为函数式接口只有一个抽象方法,它可以自动将Lambda表达式绑定到函数式接口的抽象方法;
当然这是我个人理解,文档中可以找到这样一句话,它是将其类比为方法:
A lambda expression is like a method: it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.
所以它其实就一个匿名类?然而:
@Test public void test() { System.out.println(this.getClass().getName()); A a = new A() { @Override public void opration() { System.out.println(this.getClass().getName()); } }; a.opration(); A a2 = ()->{System.out.println(this.getClass().getName());}; a2.opration(); } 输出: Basic.JavaBasicTests Basic.JavaBasicTests$3 Basic.JavaBasicTests Process finished with exit code 0
所以这里可以看出来,匿名类中this关键字指向的是匿名类本身对象,而在Lambda表达式中this关键字竟然指向当前对象,这也解释了为了什么我当初在Lambda表达式中用this关键字死活访问不到函数式接口的默认方法和常量的原因;
实战应用
再说函数式接口
我们已经知道函数式接口的作用了,但其实我们不需要自己去实现函数接口,Java8已经根据内置了几种不同类型的函数式接口;
- Predicate: A property of the object passed as argument
- Consumer: An action to be performed with the object passed as argument
- Function: Transform a T to a U
- Supplier: Provide an instance of a T (such as a factory)
- UnaryOperator: A unary operator from T -> T
- BinaryOperator: A binary operator from (T, T) -> T
这里没必要一一列举了,如果自己需要实现一个支持Lambda表达式的方法,只需要选用合适的函数式接口就行了,其实只是一种规范;
下面一个demo足够:
Consumer的应用demo
class Class { private List<Student> list = new ArrayList<>(); public void addStudent(Student student){ list.add(student); } public void showStudents(Consumer<Student> consumer){ for (Student student : list){ consumer.accept(student); } } } class Student{ private String name; private char sex; private Double height; public String getName() { return name; } public Student setName(String name) { this.name = name; return this; } public char getSex() { return sex; } public Student setSex(char sex) { this.sex = sex; return this; } } public class Tests { @Test public void test(){ Class clazz = new Class(); clazz.addStudent(new Student().setName("000").setSex('男')); clazz.addStudent(new Student().setName("002").setSex('女')); clazz.showStudents((s)-> System.out.println(s.getName())); } }
总结
所以总的来说,就是为了简化代码,封装我们的操作,所以引入了函数式接口的概念,而Lambda表达式表示了函数式接口中抽象方法的匿名实现;但是,因为这个接口只有一个抽象方法,因此Lambda表达式可以看做是这个接口的匿名实现;不过和匿名类相比其实还是有很多限制的;
Lambda表达式在Java8中的应用比较多,特别是对集合类的操作;比如sort方法、foreach方法等等;其中Stream API也是一大特点,但是也不过是对函数式接口的具体应用,还有Method Reference(方法引用)这些新特性,详细的了解需要看官方文档或者源码,文档才是最完整和权威的;
综上:
They provide a clear and concise way to represent one method interface using an expression.
The Java® Language Specification(Java SE 8 Edition)
Java™ Platform API Doc Standard Ed. 8
来源:https://www.cnblogs.com/fengwbetter/p/9420858.html