文章目录
1. 函数式编程思想
在数学中,函数就是有输入量、输出量的一套计算方案,也就是 “拿数据做操作”。
面向对象思想强调必须通过对象的形式来做事情,而函数式思想则尽量忽略面向对象的复杂语法,它强调做什么,而不是以什么形式去做。我们接下来要学习的 Lambda 表达式就是函数式思想的体现。
//需求:启动一个线程,在控制台输出一句话,多线程程序启动了
package com.zxe;
public class Test {
public static void main(String[] args) {
//1.实现类的方式实现接口
MyRunnable my = new MyRunnable();
Thread t = new Thread(my);
t.start();
//2.匿名内部类的方式改进
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("多线程程序启动了!");
}
}).start();
//3.Lambda表达式的方式改进
new Thread(() -> {
System.out.println("多线程程序启动了!");
}).start();
}
}
2. Lambda 的标准格式
() -> {
System.out.println("多线程程序启动了!");
}
Lambda 表达式的代码分析:
① 组成 Lambda 表达式 的三要素:形式参数、箭头、代码块;
② () 里面的内容是形式参数,如果有多个参数,参数之间用逗号隔开,如果没有参数,留空即可;
③ -> 用箭头指向后面要做的事情,由英文中画线和大于符号组成,固定写法;
④ {} 包含一段代码,我们称之为代码块,可以看成是方法体中的内容,也就是我们具体要做的事情。
Lambda 表达式的使用前提,必须有一个接口,且接口中有且仅有一个抽象方法!
3. Lambda 练习
3.1 抽象方法无参无返回值
package com.zxe;
public interface Eatable {
void eat();
}
package com.zxe;
public class Test {
public static void main(String[] args) {
Eatable e = () -> {
System.out.println("吃什么?");
};
e.eat();
}
}
有了 Lambda 表达式之后就不需要接口的实现类了,你也可以把 Lambda 表达式作为该接口的实现类对象,调用接口的方法!
3.2 抽象方法带参无返回值
package com.zxe;
public interface Eatable {
void eat(String food);
}
package com.zxe;
public class Test {
public static void main(String[] args) {
Eatable e = (String s) -> {
System.out.println("吃" + s);
};
e.eat("大白菜");
}
}
3.3 抽象方法带参带返回值
package com.zxe;
public interface GetSum {
int sum(int a, int b);
}
package com.zxe;
public class Test {
public static void main(String[] args) {
GetSum g = (int a, int b) -> {
return a + b;
};
int result = g.sum(10, 20);
System.out.println(result);
}
}
4. Lambda 的省略模式
① 参数的类型可以省略,如果有多个参数,不能只省略一个;
② 如果参数有且仅有一个,那么小括号也可以省略;
③ 如果代码块中的语句只有一条,可以省略花括号和分号;
④ 如果有 return,且代码块中的语句只有一条时,return 也要省略掉。
//省略前:
GetSum g = (int a, int b) -> {
return a + b;
};
//省略后:
GetSum g = (a, b) -> a + b;
5. Lambda 的注意事项
① 使用 Lambda 必须要有接口,并且要求接口中有且仅有一个抽象方法;
② 必须有上下文环境,才能推到出 Lambda 对应的接口。
//1.根据局部变量的赋值得知Lambda对应的接口
Runnable r = () -> System.out.println("Lambda表达式!");
//2.根据调用方法的参数得知Lambda对应的接口
new Thread(() -> System.out.println("Lambda表达式!")).start();
6. Lambda 和匿名内部类区别
① 匿名内部类可以是接口,也可以是抽象类,还可以是具体类,而 Lambda 表达式只能是接口;
② 如果接口中只有一个抽象方法,可以使用 Lambda 表达式,也可以使用匿名内部类,但是如果接口中由于多个抽象方法,就只能使用匿名内部类,不能使用 Lambda 表达式了;
③ 匿名内部类编译之后,会产生一个单独的 class 字节码文件,而 Lambda 表达式编译之后,是不会产生字节码文件的,对应的字节码会在运行的时候动态生成。