面向对象的思想
- 做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.
函数式编程思想
- 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程
Lamdba的基本格式
Lambda省去面向对象的条条框框,格式由3个部分组成:
- 一些参数
- 一个箭头
- 一段代码
Lambda表达式的标准格式为:
(参数类型 参数名称) -> { 代码语句 }
格式说明:
- 小括号内的语法与传统方法参数列表一致(接口中抽象方法的参数列表),无参数则留空;多个参数则用逗号分隔。
->
是新引入的语法格式,代表指向动作(传递的意思,把参数传递给方法体{})。- 大括号内的语法与传统方法体要求基本一致。
接下来通过实现Runnable接口来创建线程,一步一步进行优化
/**
* 通过实现Rubbable接口来创建线程
*/
public class Thread implements Runnable{
@Override
public void run() {
System.out.println("通过实现Runnable接口来创建线程"+Thread.currentThread().getName());
}
public static void main(String[] args) {
//创建Runnable接口的实现类对象
Thread thread = new Thread();
//创建Thread类对象,构造方法中传递Runnable接口的实现类
Thread thread = new Thread(thread);
//调用start方法,开启新线程,执行run方法
thread.start();
//简化方式一
//匿名内部类,使用接口来接收
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println("通过实现Runnable接口来创建线程"+Thread.currentThread().getName());
}
};
new Thread(runnable).start();
//继续简化
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通过实现Runnable接口来创建线程"+Thread.currentThread().getName());
}
}).start();
//使用lambda创建线程
/**
* - 前面的一对小括号即`run`方法的参数(无),代表不需要任何条件;
* - 中间的一个箭头代表将前面的参数传递给后面的代码;
* - 后面的输出语句即业务逻辑代码。
*/
new Thread(() -> System.out.println("通过继承Thread类来创建线程"+Thread.currentThread().getName()) ).start();
}
}
使用Lambda标准格式(无参数无返回值)
给定一个厨子Cook
接口,内含唯一的抽象方法makeFood
,且无参数、无返回值。如下:
public interface Cook {
void makeFood();
}
使用Lambda的标准格式调用invokeCook
方法,打印输出“吃饭啦!”的字样
public class Democook {
public static void main(String[] args) {
//调用invokeCook方法,参数是Cook接口,传递Cook接口的匿名内部类对象
invokeCook(new Cook() {
@Override
public void makeFood() {
System.out.println("吃饭了");
}
});
//小括号代表Cook接口makeFood抽象方法的参数为空,大括号代表makeFood的方法体
invokeCook(()->{
System.out.println("吃饭了");
});
}
//定义一个方法,参数传递cook接口,方法内部调用Cook接口中的方法makeFood
public static void invokeCook(Cook cook){
cook.makeFood();
}
}
使用Lambda标准格式(有参数有返回值)
需求:
使用数组存储多个Person对象,对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
public class Person {
private String name;
private int age;
// 省略构造器、toString方法与Getter Setter
}
public class Demo02arrays {
public static void main(String[] args) {
Person[] arr = {
new Person(23,"盖伦"),
new Person(19,"女警"),
new Person(28,"小炮")
};
/*
//对数组中的Person对象使用Arrays的sort方法,通过年龄进行升序(前边-后边)排序
Arrays.sort(arr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
*/
//使用lambda表达式,简化匿名内部类
Arrays.sort(arr,(Person o1,Person o2)->{
return o1.getAge()-o2.getAge();
});
//遍历数组
for (Person person : arr) {
System.out.println(person);
}
}
}
给定一个计算器Calculator
接口,内含抽象方法calc
可以将两个int数字相加得到和值:
public interface Calculator {
int calc(int a, int b);
}
public class DemoInvokeCalc {
public static void main(String[] args) {
invokeCalc(12,13, new Calculator() {
@Override
public int calc(int a, int b) {
return a+b;
}
});
//小括号代表Calculator接口calc抽象方法的参数
invokeCalc(12,13,(int a,int b)->{
//大括号代表大括号代表calc的方法体
return a+b;
});
}
public static void invokeCalc(int a, int b, Calculator calculator){
int result = calculator.calc(a, b);
System.out.println("结果是:"+result);
}
}
Lamdba表达式的使用前提
Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
- 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。
无论是JDK内置的Runnable
、Comparator
接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。 - 使用Lambda必须具有上下文推断。
也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
备注:有且仅有一个抽象方法的接口,称为“函数式接口”