java8新特性从入门到应用 第一章 Lambda表达式及FunctionalInterface函数接口
java8 是java 的一个重大版本 其中较java7之前的版本更新内容多达十几项
且作为一个长期支持版本也被各大公司和开发人员所接受,从而逐渐成为主流。Spring boot 2.0 更是直接舍弃了java8之前的版本,最低支持java8. 可见java8的迷人之处,本系列将记录我学习java8的各种新特性。及帮助阅读此文章的同学尽快适应java8的脚步(截至写此文章前java11已经面世,学的不如发展的快呀!!!)。
Lambda表达式
Lambda表达式 是java8引入的一颗重量级语法糖 如果同学之前有接触过其他编程语言(Groovy、Scala、js等)一定对Lambda表达式很熟悉。而java的Lambda姗姗来迟。
以下仅以java8中新加入的 List.forEach()
进行举例说明。
- 先看一下无Lambda时
List.forEach()
的用法:
List<String> list= Arrays.asList("a","b","c");
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
可以看出上面的语句非常之啰嗦 我们只想对list中的值进行输出为什么还要定义匿名类,还要写方法?
- 于是拯救万千程序猿的Lambda来了,上面的可简写为:
List<String> list= Arrays.asList("a","b","c");
list.forEach((Object a)->{
System.out.println(a);
});
是不是比上面的简化多了。但这还不够,既然上面已经对 list
的泛型进行了定义,为什么还要我们去声明一个 Object
?
- java8给我们带来了更好的类型推断,于是可以接着简化:
List<String> list= Arrays.asList("a","b","c");
list.forEach(a->{
System.out.println(a);
});
既如此,还不够。大括号回车党 有意见了 这句代码中只有一个输出语句为什么还要一对大括号?于是
- 终极版:
List<String> list= Arrays.asList("a","b","c");
list.forEach(a->System.out.println(a));
注意:当大括号省略时
;
号 也必须同时省略
对比一下第一版没有Lambda时的情况是不是简化了很多?
lambda表达式的特征: 1
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
常用 Lambda写法:
- 单参数单语句无返回值
a -> System.out.println(a)
- 多参数单语句无返回值
(a,b) -> System.out.println(a+":"+b)
- 多参数多语句无返回值
(a,b) -> {
if(a==b){
System.out.println(a+":"+b);
}
}
4.多参数多语句有返回值
(a,b) -> {
if(a==b){
return a;
}else{
return b;
}
}
5.单参数单语句有返回值 a -> a
FunctionalInterface函数接口
FunctionalInterface函数接口(以下将直呼其中文名称 函数接口
) 严格来说不是一个新的东西,它只是一个新的定义其非严格定义如下
所有只有一个未被实现的方法的接口被统称为
函数接口
以刚才的List.forEach()
举例: 其参数为 java.util.function.Consumer<T>
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
// default和 static 修饰的方法 是有实现的
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
其中未被实现的方法只有 accept(T t)
一个所以 java.util.function.Consumer<T>
类是一个 函数接口
而实际上Lambda表达式实际上就是隐式实现了这个接口 并重写了其中未被实现的方法(accept(T t)
)。
我们在来看一下 List.forEach()
方法内部:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
其实就是一个迭代循环将list中的元素当作 accept(T t)
方法的参数传入进去执行而已
一切都已经很简单了 Lambda表达式不过是编译器为了使开发变得简单,使得一个小花样而已。
@FunctionalInterface 注解
@FunctionalInterface 注解并没有实际含义 对接口是不是属于函数接口并没有影响,其主要作用是用于提示开发人员和告诉编译器 请检查被@FunctionalInterface标记的接口是否只有一个未被实现的方法。
java 8中新增的函数接口
java8中新增的函数接口在 java.util.function
包下
接口 | 参数 | 返回值 |
---|---|---|
BiConsumer<T,U> | T U | void |
BiFunction<T,U,R> | T U | R |
BinaryOperator< T > | T T | T |
BiPredicate<T,U> | T U | boolean |
BooleanSupplier | boolean | |
Consumer< T > | T | void |
DoubleBinaryOperator | double double | double |
DoubleConsumer | double | viod |
DoubleFunction< R > | double | R |
DoublePredicate | double | boolean |
DoubleSupplier | double | |
DoubleToIntFunction | double | int |
DoubleToLongFunctio | double | long |
DoubleUnaryOperator | double | double |
Function<T,R> | T | R |
IntBinaryOperator | int | int |
IntConsumer | int | viod |
IntFunction< R > | int | R |
IntPredicate | int | boolean |
IntSupplier | int | |
IntToDoubleFunction | int | double |
IntToLongFunction | int | long |
IntUnaryOperator | int | int |
LongBinaryOperator | long long | long |
LongConsumer | long | viod |
LongFunction< R > | long | R |
LongPredicate | long | boolean |
LongSupplier | long | |
LongToDoubleFunction | long | boolean |
LongToIntFunction | long | int |
LongUnaryOperator | long | long |
ObjDoubleConsumer< T > | T double | void |
ObjIntConsumer< T > | T | int |
ObjLongConsumer< T > | T | long |
Predicate< T > | T | boolean |
Supplier< T > | T | |
ToDoubleBiFunction<T,U> | T U | double |
ToDoubleFunction< T > | T | double |
ToIntBiFunction<T,U> | T U | int |
ToIntFunction< T > | T | int |
ToLongBiFunction<T,U> | T U | long |
ToLongFunction< T > | T | long |
UnaryOperator< T > | T | T |