一、函数式编程思想概述
https://www.runoob.com/java/java8-lambda-expressions.html
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象强调“必须通过对象的形式来做事情”,做事情之前首先要创建一个对象
函数式思想则尽量忽略面向对象的复杂语法:”强调做什么,而不是以什么形式去做”,我们要学习的Lambda表达式就是函数时思想的体现
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
需求:启动一个线程,在控制台输出一句话:多线程启动了
1.1 方式一 创建类实现Runnable接口
定义一个类MyRunnable实现Runnable接口,重写run()方法
创建MyRunable类对象
创建Thread类的对象,把MyRunnable的对象作为构造参数传递
启动线程
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("多线程程序启动了");
}
}
public class LambdaTest {
public static void main(String[] args) {
MyRunnable my = new MyRunnable();
Thread t = new Thread(my);
t.start();
}
}
1.2 方式二 匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("ssss");
}
}).start();
1.3 方式三 lambda表达式
简洁,不用创建类
new Thread( ()->{
System.out.println("多线程程序启动");
}).start();
Lambda表达式的代码分析
new Thread( ()->{
System.out.println("多线程程序启动");
}).start();
():里面没有内容,可以看成是方法形式参数为空
->:用箭头指向后面要做的事情
{}:包含一段代码。我们称之为代码块
(形式参数)->{代码块}
形式参数:如果有多个参数,参数之间用逗号隔开
->:由英文中划线和大于符号组成,固定写法,代表指向动作
代码块:我们具体要做的事情
二、Lambda表达式练习
2.1 抽象方法无参无返回值

public interface Eatable {
void eat();
}
public class EatableImpl implements Eatable{
@Override
public void eat() {
System.out.println("好好好");
}
}
public class EatableDemo {
public static void main(String[] args) {
Eatable e = new EatableImpl();
userEatable(e);
}
private static void userEatable(Eatable e){
e.eat();
}
}
上面的代码可以简化
userEatable(()->{
System.out.println("好好好");
} );
下面这个就不需要实现类的
public class EatableDemo {
public static void main(String[] args) {
userEatable(()->{
System.out.println("好好好");
} );
}
private static void userEatable(Eatable e){
e.eat();
}
}
2.2 抽象方法带参无返回值

定义接口
public interface Flyable {
void fly(String s);
}
public class FlyableDemo {
public static void main(String[] args) {
userFlyable( (String s)->{
System.out.println(s);
System.out.println("好好好");
});
}
private static void userFlyable(Flyable f){
f.fly("风和日丽");
}
}

2.3 抽象方法带参带返回值

public class AddableDemo {
public static void main(String[] args) {
userAddable( (int x,int y)->{
return x+y;
});
}
private static void userAddable(Addable a){
int sum = a.add(10,20);
System.out.println(sum);
}
}
a.add(10,20)中的10和20最终传递给了int x,int y,然后通过lambda表达式将x与y相加并返回给sum
public interface Addable {
int add(int x,int y);
}
三、Lambda表达式的省略模式
3.1 参数的类型可以省略
虽然能省略,但是多个参数的情况下不能只省略一个
userAddable( ( x, y)->{
return x+y;
});
3.2 参数有且只有一个,参数可以省略
public class FlyableDemo {
public static void main(String[] args) {
userFlyable( s->{
System.out.println(s);
});
}
private static void userFlyable(Flyable f){
f.fly("风和日丽");
}
}
3.3 代码块语句只有一条,可以省略大括号和分号
public class FlyableDemo {
public static void main(String[] args) {
userFlyable( s->System.out.println(s) );
}
private static void userFlyable(Flyable f){
f.fly("风和日丽");
}
}
3.4 代码块语句只有一条,return也要省略掉
userAddable( ( x, y)-> x+y);
四、注意事项
有一个接口(抽象类不可以),接口中有且只有一个抽象方法
使用lambda的时候必须有上下文环境,才能推导出Lambda对应的接口

匿名内部类编译之后会多出一个“.class”文件,而lambda不会多出,lambda字节码会在运行的时候动态生成
匿名内部类可以是接口,可以是抽象类,还可以是具体类