1. Lambda表达式
λ,Lambda 表达式是一个匿名函数,可以包含表达式和语句
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”.而我们要学习的Lambda表达式就是函数式思想的体现
public class Test {
public static void main(String[] args) {
//普通
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr);
t.start();
//匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("启动多线程2");
}
}).start();
//Lambda方式
new Thread(() -> {
System.out.println("启动多线程3");
}).start();
}
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("启动多线程");
}
}
}
格式:(形式参数)->{代码块}
- ():如果又多个参数,用逗号隔开,没有参数,留空
- ->:
- {}:代码块
1.1. 例子
Lambda表达式使用前提:
- 又一个接口
- 接口中有且只有一个抽象方法
public interface Addable {
int add(int x,int y);
}
public interface Flyable{
void fly(String s);
}
public class AddDemo {
static class AddableReal implements Addable {
@Override
public int add(int x, int y) {
System.out.println("这是普通方式,只返回x");
return x;
}
}
public static void main(String[] args) {
//使用普通的方式,需要实现接口
AddableReal addableReal = new AddableReal();
int sum = addableReal.add(1, 2);
System.out.println(sum);
useAddable(new Addable() {
@Override
public int add(int x, int y) {//匿名内部类,实现Addable中的add方法
System.out.println("这是匿名内部类,返回x+y");
return x + y;
}
});
useAddable((int x, int y) -> {
System.out.println("这是Lambda,返回x+y+y");
return x + y + y;
});
useAddable((x, y) -> {
System.out.println("这是Lambda省略模式,省略参数类型,返回x-y");
return x - y;
});
useAddable((x,y)->x+y);//只有一句话,可以省略大括号和分号和return
useFlyable(s->{
System.out.println(s);//只有一个参数,可以省略(),因为是通过Flable接口,里面的方法要求参数是String
});
useFlyable(s->System.out.println(s));//只有一个参数,可以省略大括号和分号
}
private static void useAddable(Addable a) {
//这里的a是接口, 具体的实现方式,是通过,类中的()->{}来实现的.
int sum = a.add(1, 5);
System.out.println(sum);
}
private static void useFlyable(Flyable f) {
f.fly("正在飞");
}
}
1.2. 重点
- 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
- 必须有上下文环境,才能推导出Lambda对应的接口
-
根据局部变量的赋值得知Lambda对应的接口:
Runnable r = () -> System.out.println("Lambda表达式"); new Thread(r).start();
-
根据调用方法的参数得知Lambda对应的接口:
-
Lambda:
new Thread( () -> System.out.println("Lambda表达式") //这里是一个Runnable接口 ).start();
-
匿名内部类:
new Thread(new Runnable() { @Override public void run() { } }).start();
-
-
1.3. Lambda表达式和匿名内部类的区别
- 所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
- 使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
- 实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件.对应的字节码会在运行的时候动态生成