函数式编程思想概述
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象思想强调“必须通过对象的形式来做事情”
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
Lambda表达式就是函数式思想的体现
体验Lambda表达式
需求:启动一个线程,在控制台输出一句话:多线程程序启动了
方式一
- 定义一个类MyRunnable实现Runnable接口,重写run()方法
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable的对象作为构造参数传递
- 启动线程
采用了实现类的方式实现需求
public class MyRunnable implements Runnable{
private int tickets = 100;
//重写run方法 实现卖票
@Override
public void run(){
sout("多线程程序启动了");
}
}
//主程序LambdaDemo
//创建MyRunnable对象
MyRunnable my = new MyRunnable();
//创建Thread类的对象,把MyRunnable对象作为构造方法的参数
Thread t1 = new Thread(my);
//启动线程
t1.start();
方式二
采用了匿名内部类方式改进
new Thread(new Runnable(){
@Override
public void run(){
sout("多线程程序启动了");
}
}).start();
方式三
采用了Lambda表达式方式改进
new Thread( () -> {
sout("多线程程序启动了");
} ).start();
Lambda表达式的标准格式
Lambda表达式的格式:
- 格式:(形式参数)->{代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
Lambda表达式的练习
Lambda表达式使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
练习1:
方式一
采用了实现类的方式实现需求
//定义一个接口
public interface Eatable{
void eat();//接口中有且仅有一个抽象方法
}
//定义一个类实现这个接口
public class EatablleImpl implements Eatable{
@Override
public void eat(){
sout("一天一苹果");
}
}
//主程序
//定义的其中一个方法
private static void useEatable(Eatable e){
e.eat();
}
//在主方法中调用这个方法
//创建接口的对象,通过多态的方式
Eatable e = new EatablleImpl();
useEatable(e);
方式二
采用了匿名内部类的方式实现需求
useEatable(new Eatable (){
@Override
public void eat(){
sout("一天一苹果");
}
});
方式三
采用了Lambda表达式方式改进
useEatable( () -> {
sout("一天一苹果");
} );
练习2:
//定义一个接口
public interface Flyable{
void fly(String s);//接口中有且仅有一个抽象方法
}
//主程序
//定义的其中一个方法
private static void useFlyable(Flyable f){
f.fly(s:"风和日丽");
}
//在主方法中调用这个方法
//创建接口的对象,通过多态的方式
Eatable e = new EatablleImpl();
useEatable(e);
方式一
采用了匿名内部类的方式实现需求
useFlyable (new Flyable (){
@Override
public void fly(String s){
sout(s);
sout("飞机自驾游")
}
});
方式二
采用了Lambda表达式方式改进
useFlyable( (String s) -> {
sout(s);
sout("飞机自驾游")
} );
练习3:
//定义一个接口
public interface Addable{
int add(int x,int y);//接口中有且仅有一个抽象方法
}
//主程序
//定义的其中一个方法
private static void useAddable(Addable a){
int sum = a.add(x:10,y:10);
sout(sum);
}
//在主方法中调用这个方法
//创建接口的对象,通过多态的方式
采用了Lambda表达式方式改进
useAddable( (int x,int y) -> {
return x+y;//这是具体的实现 不看方法名,应该看具体的实现
} );
Lambda表达式的省略模式
//定义一个接口
public interface Addable{
int add(int x,int y);
}
//定义一个接口
public interface Flyable{
void fly(String s);
}
//测试类
useAddable( (int x,int y) -> {
return x+y;//这是具体的实现 不看方法名,应该看具体的实现
} );
//参数的类型可以省略 但是又多个参数的情况下,不能只省略一个,要么都省略,要么都不省略
useAddable( (x,y) -> {
return x+y;//这是具体的实现 不看方法名,应该看具体的实现
} );
useFlyable( (String s) -> {
sout(s);
} );
//省略掉类型
useFlyable( (s) -> {
sout(s);
} );
//如果参数有且仅有一个,小括号也可以省略
useFlyable( s -> {
sout(s);
} );
//如果代码块的语句只有一条,可以省略大括号和分号 如果有return,return也要省略掉,
useFlyable( s -> sout(s));
//如果有return,return也要省略掉,只针对代码块语句只有一条的情况下
useAddable( (x,y) -> x+y );
//定义的其中一个方法
private static void useFlyable(Flyable f){
f.fly(s:"风和日丽");
}
//定义的其中一个方法
private static void useAddable(Addable a){
int sum = a.add(x:10,y:10);
sout(sum);
}
省略规则:
- 参数的类型可以省略 但是有多个参数的情况下,不能只省略一个,要么都省略,要么都不省略
- 如果参数有且仅有一个,小括号也可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号 如果有return,return也要省略掉
Lambda表达式的注意事项
//定义一个接口
public interface Inter{
void show();
//在接口中添加一个方法
//void method();
}
//定义的其中一个方法 使用这个接口作为参数的方法
private static void useInter(Inter i){
i.show();
}
//主方法的程序
//使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
useFlyable( (String s) -> {
sout("好好学习");
} );
//化简
useFlyable( s -> sout("好好学习") );
//使用Lambda必须有上下文环境,才能推导出Lambda对应的接口
new Thread(new Runnable(){
@Override
public void run(){
sout("匿名内部类");
}
}).start();
Runnable r = () -> sout("好好学习");//根据局部变量的类型来推导lambda表达式对应的接口
new Thread(r).start();
//优化
new Thread(() -> sout("好好学习")).start();
注意事项:
Lambda表达式和匿名内部类的区别
//定义一个接口
public interface Inter{
void show();
}
//定义一个类
public abstract class Animal{
public abstract void method();//无参无返回值
}
//定义一个类
public class Student{
public void study(){
sout("爱生活");
}
}
//测试类
//在测试类里定义方法调用
private static void useStudent(Student s){
s.study();
}
private static void useAnimal(Animal a){
a.method();
}
private static void useInter(Inter i){
i.show();
}
//主函数
//先写匿名内部类的
useInter (new Inter (){
@Override
public void show(){
sout("接口")
}
});
useAnimal (new Animal (){
@Override
public void method(){
sout("抽象类")
}
});
useStudent (new Student (){
@Override
public void study(){
sout("具体类")
}
});
//用Lambda表达式调用
useInter(() -> sout("接口"));
useAnimal(() -> sout("抽象类"));//这个报错
useStudent(() -> sout("具体类"));//这个也报错
匿名内部类输出
接口中存在多个方法时,使用匿名内部类可以调用方法
Laambda表达式输出
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。