Lambda表达式
1. Lambda表达式介绍
Lambda表达式体现的是函数式编程思想,我们只需将执行的代码放到函数中(函数指的是类中方法,就是重写的抽象方法)
Lambda是一种匿名函数
public static void main(String[] args) {
//采用匿名函数
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是匿名函数!");
}
});
//采用Lambda表达式
new Thread(()->{
System.out.println("我是Lambda表达式!");
} );
}
2. Lambda标准格式
2.1 表达式
(参数列表) -> {}
(参数列表):参数列表
->:起连接作用,无意义
{}:方法体
2.1.1 无参数,无返回值
//接口
public interface ISleep {
void sleep();
}
//实现类
public static void main(String[] args) {
ISleep iSleep = () -> {
System.out.println("我要睡觉!");
};
sleep(iSleep);
}
public static void sleep(ISleep s){
s.sleep();
}
2.1.1 有参数,有返回值
有参数,有返回值
public interface IEat {
int eat(String name);
}
public static void main(String[] args) {
eat((String name)->{
System.out.println(name+"好好吃");
return 5;
});
}
public static void eat(IEat e){
int i = e.eat("披萨");
System.out.println(i);
}
小结:方法参数列表是接口,就可以采用Lambda表达式。
3. Lambda底层实现原理
3.1 匿名内部类剖析
3.1.1 class文件进行反汇编得
3.2 Lambda表达式剖析
3.2.1 java内部工具反汇编——得到新增方法
javap -c -p 类.class
-c:表示对代码进行反汇编
-p:显示所有类和成员
java内部工具进行反汇编后,结果会新增一个方法lambda$main$0();Lambda其中表达式内容就位于这。
3.2.2 运行反汇编的到class
java -Djdk.internal.lambda.dumpProxyClasses 包名.类名
运行后会生成内部类class的,打开会发现和匿名内部类相差无几。
小结(记得切换路径)
匿名内部类在编译时会形成一个字节码文件。
Lambda表达式在程序运行时会生成一个类
1.新增一个方法,该方法的内容就是Lambda表达式中的代码(**这是匿名内部类和Lambda表达式区别之处**)
2.会创建一个匿名内部类,实现接口,重写抽象方法
3.在重写后的方法中调用新增方法
4. Lambda省略模式
4.1 可省略步骤
在Lambda标准格式的基础上,使用省略写法的规则为:
1.小括号内参数的类型可以省略
2.如果小括号内有且仅有一个参数,则小括号可以省略
3.如果大括号内有且仅有一个语句,可以同时省略大括号、return关键字及语句分号
5. Lambda使用的前提条件
Lambda的语法非常简洁,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意:
5.1 方法的参数或是局部变量类型必须为接口
5.2 接口中有且仅有一个抽象方法
//接口
@FunctionalInterface //检测是否只有一个抽象方法
public interface IFlyable {
void flying1();
//当接口有两个抽象方法时,lambda表达式不知道为谁重写
void flying2();
}
public static void main(String[] args) {
//方法参数是接口时
test(()->{
System.out.println("方法参数是接口时,我会飞~");
});
//局部变量类型为接口接口时
IFlyable flyable = () -> {
System.out.println("局部变量类型为接口接口时,我会飞~");
};
test(flyable);
}
public static void test(IFlyable fly){
fly.flying1();
}
6. Lambda与匿名内部类对比
目标
了解Lambda和匿名内部类在使用上的区别
1.所需的类型不一样
匿名内部类需要的类型可以是类抽象类接口
Lambda表达式,需要的类型必须是接口
2.抽象方法的数量不一样
匿名内部类所需的接口中抽象方法的数星随意
Lambda表达式所需的接口只能有一个抽象方法
3.实现原理不同
匿名内部类是在编译后会形成class
Lambda表达式是在程序运行的时候动态生成class
小结
当接口中只有一个抽象方法时,建议使用Lambda表达式,,