这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
前些日子在看Spring cloud gateway源码时,常看到lamda表达式。由于自己对lamda表达式不是很熟悉,特此重新学习。
前言
Lambda 表达式是 Java 8 发布的最重要新特性。它允许把函数作为一个方法的参数,传递进方法中去。使用 Lambda 表达式可以使代码变的更加简洁紧凑。需要注意的是lamda表达式的使用依赖于函数式接口。
为什么要使用lamda表达式
目前来说,使用lamda表达式最突出的优点在于简化代码,使代码变的更加简洁紧凑。
以最常见的线程创建为例:
-
传统方式
public class Test { public static void main(String[] args) { Thread thread = new Thread(new RunTest()); thread.run(); } } class RunTest implements Runnable{ @Override public void run() { System.out.println(123); } } -
普通匿名内部类的方式
public class Test { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("123"); } }); thread.run(); } } -
lamda表达式方式
public class Test { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println(123); }); thread.run(); } }
通过比较可以发现,使用lamda表达式的方式代码更为简洁。
相关概念
lamda表达式格式
lamda表达式一般由以下格式构成:
(parameters) -> expression
或
(parameters) ->{ statements; }
具体见以下示例
()->5; // 无参数,返回5
(int x,int y)->5*x+6*y; // 多参数,返回5*x+6*y的结果
x->5*x // 单参数,返回5*x的结果。当只有一个参数时,可以忽略括号和参数类型
函数式接口
lamda表达式的使用依赖于函数式接口。所谓函数式接口,是指任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。
代码示例如下所示:
@FunctionalInterface
public interface TestInterface {
int test(int x);
}
其中,为了避免后来人给这个接口添加函数后,导致该接口有多个函数,不再是函数式接口,我们可以在接口类的上方声明 @FunctionalInterface。
用lamda实现函数式接口的方式如下:
public class Test {
public static void main(String[] args) throws Exception {
TestInterface test;
test = x->{
System.out.println(5*x);
return 5*x;
};
int num = test.test(6);
System.out.println(num);
}
}
由以上代码可见,对函数式接口赋值lamda语句,本质上是对接口方法进行实现。
方法引用
除了普通lamda表达式->类型外,还有另外一种写法,被称为方法引用。
所谓方法引用,就是指如果一个方法的参数一致,返回值类型相同,那么就可以通过方法引用的方式对函数式接口进行赋值。
方法引用的格式如下:
// 类名::方法名
Integer::parseInt
代码示例如下:
public class Test {
public static void main(String[] args) throws Exception {
TestInterface testInterface;
testInterface = Integer::parseInt;
int test1 = testInterface.test("123");
// 上述代码等价于以下代码
testInterface = x -> {
return Integer.parseInt(x);
};
int test2 = testInterface.test("123");
}
}
除此之外,方法引用还有以下情况:
-
构造器引用: 它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car ); -
静态方法引用: 它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide ); -
特定类的任意对象的方法引用: 它的语法是Class::method实例如下:
cars.forEach( Car::repair ); -
特定对象的方法引用: 它的语法是instance::method实例如下:
final Car police = Car.create( Car::new ); cars.forEach( police::follow );