Java8实战-Lambda表达式
lambda是什么
原书中是这么描述的:可以把lambda表达式理解为简洁地表示可传递的匿名函数的一种方式
就是没有名字,但是有参数列表、函数主体、返回类型,可能还存在一个可抛出的异常列表。
lambda的几个主要特点:
- 匿名:不像普通的方法一样有一个明确的名称。
- 函数:为什么是函数,因为lambda函数不想方法那样属于某个特定的类。
- 传递:lambda表达式可以作为参数传递给方法或存储在变量中。
- 简洁:不需要像匿名类那样写很多模板代码。
使用lambda表达式可以使你的代码变得更清晰、更灵活。
比如,利用lambda表达式,可以更为简洁地自定义一个Comparator对象。
// 先前
Comparator<Apple> comparator = new Comparator<>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight().compareTo(o2.getWeight());
}
};
// 之后(使用lambda表达式)
Comparator<Apple> comparator1 = (Apple a1, Apple a2) ->
a1.getWeight().compareTo(a2.getWeight());
很好,你现在已经学会lambda了,快去大展身手吧
不可否认,下面的代码更加简洁明了,更加清晰。其实还可以进一步地简化代码,之后会遇到。
上面展示地lambda表达式有三个部分:
- 参数列表:这里用了Comparator中compare方法的参数,两个Apple
- 箭头: ->把参数列表和lambda主体分隔开来
- lambda主体:比较两个Apple的重量,表达式就是lambda的返回值。
lambda的基本语法是 (参数) -> 表达式
或者 (参数) -> { 语句; }
怎么使用lambda
只要你想,你可以在代码中的任何地方使用lambda…..
你可以在函数式接口上使用lambda表达式。那么函数式接口是个啥?简单来说,函数式接口就是只定义一个抽象方法的接口。比如Runnable
、Comparator
之类的,这些接口上都有一个@FunctionalInterface
进行标注
这个注解有以下特点:
- 该注解只能标记在”有且仅有一个抽象方法”的接口上。
- JDK8接口中的静态方法和默认方法,都不算是抽象方法。
- 接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
- 该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
例如Runnable接口:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
这就是一个标准的函数式接口。
那么使用函数式接口可以干什么呢?lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(是函数式接口一个具体实现的实例)。
当然使用匿名内部类也可以完成同样的事情,但是你需要提供一个实现,然后再直接内联将它实例化。
private static void runnableTest() {
// 使用lambda
Runnable runnable1 = () -> System.out.println("hello 1");
// 使用匿名类
Runnable runnable2 = new Runnable() {
@Override
public void run() {
System.out.println("hello 2");
}
};
// 打印hello 1
process(runnable1);
// 打印hello 2
process(runnable2);
// 利用直接传递的lambda打印hello 3
process(() -> System.out.println("hello 3"));
}
private static void process(Runnable r) {
r.run();
}
输出:
想要了解更多,可以查看原书,懒得写了XD