一、概念
Lambda表达式是Java 8中的一个新特性,它允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变得更加简洁紧凑。
简单来说,就是一个简化匿名内部类写法的表达式。
二、语法
(parameters) -> expression
或
(parameters) ->{ statements; }
三、特征
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指明表达式返回了一个数值。
四、实例
1.最常见的使用Lambda表达方式的场景,就是使用它编写线程方法,如下:
new Thread( ()-> {
System.out.println("我实现了Runable的run方法");
}
).start();
它等价于下面这种写法:
new Thread( new Runnable() {
@Override
public void run(){
System.out.println("我用匿名内部类实现了Runnable的run方法");
}
}
).start();
比较下这两种写法,就能发现:
(1)Lambda表达式把【 new Runnable() 】省略了,只剩下了一个【 () 】,表明给Thread传入的参数。
因为Thread只有一个这种样子的构造方法,并且传入的参数还是一个接口类型的(interface),所以可以使用Lambda表达式省略。
Thread的构造方法如下:
//参数Runnable是一个接口类型的参数
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
假如Thread还有另一个类似的构造方法,则无法使用Lambda表达式,因为它会不知道你想省略哪一个接口类型的参数。
例如,这种情况下无法使用Lambda表达式:
//Runnable是一个接口类型的参数
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
//Runnable2是一个接口类型的参数
public Thread(Runnable2 target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
//此时,无法使用Lambda表达式。【因为不知道省略的是new Runnable()还是new Runnable2()】
(2)Lambda表达式把【 public void run() 】也省略了,只剩下一个【 -> 】,表明重写接口的某个抽象方法。
因为Runnable中只有一个抽象方法,所以可以使用Lambda表达式省略。
Runnable的代码如下:
public interface Runnable {
public abstract void run();
}
假如Runnable中有两个以上的抽象方法,则无法使用Lambda表达式,因为它会不知道你想重写哪一个抽象方法。
例如,这种情况下无法使用Lambda表达式:
public interface Runnable {
public abstract void run();
public abstract void run2();
}
五、具体用法
1.先写一个接口
public interface MyInterface{
//注意只能有一个抽象方法,如果还有其它的抽象方法,则无法使用Lambda表达式(不过匿名内部类写法不受影响,可以正常使用)
public abstract String example(String str);
}
2.正常情况下,匿名内部类写法
MyInterface mi = new MyInterface() {
@Override
public String example(String str){
return "匿名内部类写法"+str;
}
}
3.Lambda表达式写法
//省略接口参数名,省略抽象方法名
MyInterface mi0 = (String str) -> {
return "Lambda表达式"+str;
};
//抽象方法参数类型可以继续省略
MyInterface mi1 = (str) -> {
return "Lambda表达式"+str;
};
//接着,抽象方法参数括号可以继续省略
MyInterface mi2 = str -> {
return "Lambda表达式"+str;
};
//抽象方法的大括号和return可以继续省略
MyInterface mi3 = str -> "Lambda表达式"+str;
4.调用执行,正常使用即可
mi.example("都一样");
mi0.example("0");
mi1.example("1");
mi2.example("2");
mi3.example("3");
六、总结
Lambda表达式可以简化匿名内部类的写法,主要省略两个地方:
(1)省略调用方法、传递参数时需要的接口类型的参数类型 (因为只有这一种,所以省略了也知道省略的是哪个)
(2)省略实现的接口中抽象方法的名称,只写方法体 (因为只有一个抽象方法,所以省略了也知道省略的是哪个)