java8/lambda?
1 lamnbda
1.1 什么是lambda
lambda:In programming languages such as lisp, python and ruby lambda is an operator used to denote anonymous functions(匿名函数) or closures(闭包), following the usage of lambda calculus(算子)
在java中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法
但是:在javaScript中,函数参数是一个函数,返回值是另一个函数的情况非常常见;javaScript是一门非常典型的函数式语言
public class SwingTest { public static void main(String[] args) { JFrame my_jFrame = new JFrame("my jFrame"); JButton my_jButton = new JButton("my jButton"); //匿名内部类,可以选择使用lambda进行替换 my_jButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { System.out.println("Button Pressed"); } }); my_jFrame.add(my_jButton); my_jFrame.pack(); my_jFrame.setVisible(true); my_jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
如下,鼠标放到指定位置,可以看到匿名的new ActionListener可以被lambda进行替换。同时仔细想想这么一堆代码,我们只需要"
System.out.println("Button Pressed");
"
//匿名内部类,可以选择使用lambda进行替换 my_jButton.addActionListener(actionEvent -> System.out.println("Button Pressed"));
同时,可以注意到上面参数actionEvent没有指定类型,这是因为借助java编译系统里面的类型推断,可以直接推断出具体的类型,所以不需要额外指出。有些时候不能推断出来的时候,需要自己额外定义说明
(param1, param2, param3) -> {
执行体
}
2 Consumer
2.1 了解Consumer
重点关注如上两种:其中consumer是java8中新提供的特性,且上述的new Consumer是一个匿名内部类,实现了Consumer接口,有唯一的accept这个方法,打印了出来。
同时,list.forEach在调用的时候,是每一个元素调用Consumer的accept方法,将其打印出来
forEach的参数是Consumer,Consumer是一个泛型接口,后面的<? super T>表示,泛型可以是T,也可以是T的父类。例如T为Integer。相反的是extend表示T以及T的子类
3 FunctionalInterface
3.1 了解functionalInterface
从1.8开始引入
An informative(通知性) annotation(注解) type used to indicate that an interface type declaration is intended(旨在) to be a <i>functional interface</i> as defined by the Java Language Specification.
Conceptually(从概念上讲), a functional interface has exactly one(精确一个,有且仅有) abstract
method. Since(因为) {@linkplain java.lang.reflect.Method#isDefault()
default methods} have an implementation, they are not abstract. If
an interface declares an abstract method overriding(覆盖) one of the
public methods(共有方法) of {@code java.lang.Object}, that also does
<em>not</em> count toward the interface's abstract method count(接口的抽象方法加一)
since any implementation of the interface will have an
implementation from {@code java.lang.Object} or elsewhere.
<p>Note that(注意的是) instances of functional interfaces can be created with
lambda expressions, method references, or constructor references.
* <p>If a type is annotated with this annotation type(使用了FunctionalInterface注解), compilers are
* required to generate an error message unless(如果不满足如下两点需要):
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat(对待) any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
3.2 测试FunctionalInterface
多个非重写的抽象方法被在该接口发现,所以报错。(这里的overriding指的是什么?指的是java.lang.Object里面的public method被重写),如下重写了toString方法,编译器认为是一个函数式接口
3.3 be created with lambda expressions
匿名内部类本质就是接口的实现。同理:函数式接口本质上只有一个抽象方法,所以接口的实现也是实现该抽象方法,所以方法名不那么重要了
forEach理解:forEach是Iterable接口的一个默认方法,为什么上述的list可以调用forEach方法呢?只能说明list接口直接/间接继承了iterable接口,下述可证。。。
对于forEach而言。这里是把行为作为参数,而不是数据
* Performs(执行) the given action for each element of the {@code Iterable} * until all elements have been processed or the action throws an * exception. Unless otherwise specified(另行指定) by the implementing class, * actions are performed in the order of iteration(迭代顺序) (if an iteration order * is specified). Exceptions thrown by the action are relayed to the * caller.(是否抛出异常取决于调用者)
3.4 分析Consumer
/** * Represents(代表) an operation that accepts a single input argument and returns no * result(不返回值). Unlike most other functional interfaces, {@code Consumer} is expected * to operate via side-effects(Consumer是有副作用的,可能修改接收的参数). * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #accept(Object)}. * * @param <T> the type of the input to the operation * * @since 1.8 */
总结:
- lambda为java添加了缺失的函数式编程特性。使得我们可以将函数当作一等公民看待
- 在将函数作为一等公民的语言中,lambda的表达式的类型是函数;但是在java中,lambda是对象。。。它们必须依附于一类特别的对象类型——函数式接口(functional interface)