lambda表达式
可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它 有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
/**
* lambda表达式简洁处理例子
*/
Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
lambdab表达式组成部分:[ () -> {} ]
- ()参数列表
- -> 箭头符号分隔lambda得参数列表和方法体
- {} 方法体
上面例子中没有{}其实是省略得写法,当方法体只有一行语句时可以省略{},包含需要若方法体中需要返回值中的return也可以省略。
1.1 函数式接口
lambda表达式实际上就是通过上下文环境进行类型推断,调用对应的函数式接口方法
那么上面是函数式接口呢?
java8中声明函数式接口的注解@FunctionalInterface上有对应的定义
/**
* 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.
*一个函数式接口有一个抽象方法,java8中增加default方法,接口中可以有具体实现的方法,这些方法不属于抽象方法,若这个接口中存在复写Object类中的方法(直接或间接),这部分抽象方法是不计算在接口抽象方法个数中计算的(例如:String toString() 接口中若存在这种方法,这个toString方法是不算作抽象方法个数的)
* <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, 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.
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
Conceptually, a functional interface has exactly one abstractmethod. Since {@linkplain java.lang.reflect.Method#isDefault()default methods} have an implementation, they are not abstract. Ifan interface declares an abstract method overriding one of thepublic methods of {@code java.lang.Object}, that also doesnot count toward the interface’s abstract method countsince any implementation of the interface will have an implementation from {@code java.lang.Object} or elsewhere.
一个函数式接口有一个抽象方法,java8中增加default方法,接口中可以有具体实现的方法,这些方法不属于抽象方法,若这个接口中存在复写Object类中的方法(直接或间接),这部分抽象方法是不计算在接口抽象方法个数中计算的(例如:String toString() 接口中若存在这种方法,这个toString方法是不算作抽象方法个数的)另外即使没有使用@FunctionalInterface注解修饰,只要满足函数式接口定义那就都是函数式接口
下面哪些接口是函数式接口?
public interface Adder{
int add(int a, int b);
}
public interface SmartAdder extends Adder{
int add(double a, double b);
}
public interface Nothing{ }
答案:只有Adder是函数式接口。
TIP:@FunctionalInterface这个标注用于表示该接口会设计成 一个函数式接口。如果你用@FunctionalInterface定义了一个接口,而它却不是函数式接 口的话,编译器将返回一个提示原因的错误。@FunctionalInterface不是必需的
1.2 lambda表达式如何做的类型检查
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。我们将这种抽象方法叫作函数描述符
举例说明
execute(() -> {});
public void execute(Runnable r){
r.run();
}Lambda() ->{}具有签名() -> void,这和Runnable中的抽象方法run的签名相匹配。请注意,此代码运
行后什么都不会做,因为Lambda是空的!
所谓签名其实可以理解为这个函数的入参是几个都是什么类型,返回值是什么。
1.3 使用lambda的步骤
- 第一步要行为参数化
- 第二步使用函数式接口来传递行为
- 执行(获取)一个行为
- 传递 Lambda
这个结合第二章练习的时候慢慢体会(后续会更新)