个人理解函数式编程可以增加灵活性,把函数作为参数进行传递,jdk1.8新增的新特性lambda表达式,以下内容仅是个人理解,如有不对请无视!
语法:(参数)->{方法体};
1,Lambda 规定接口中只能有一个需要被实现的方法,静态方法和default方法不需要被实现所以不影响
如下:
@FunctionalInterface //标名接口为函数接口的注解
interface A{
void a(String a);
static void b(String a,String b){};//静态方法
default void c(String a,String b){};//默认方法有一个默认实现,可以被实现类覆盖
}
A b = (String a) -> { System.out.println(a);};
b.a("方法被调用了01");
个人理解:函数式编程的思想,把lambda表达式(函数)赋给一个函数接口类型的变量接收,此变量可作为参数传递
上述的lambda表达式理解:b变量相当于A接口类型的实现类实例,参数a是实现方法的参数,System.out.println(a);是实现类方法的方法体
有此可类推创建线程的lambda表达式写法:r代表实现了Runnable接口的实例对象,并可作为参数传入new Thread(r)中
Runnable r = () -> {
System.out.println("线程启动了");
};
Thread t = new Thread(r);
t.start();
2,lambda方法调用 方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象。
有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda表达式的接口快速指向一个已经被实现的方法。
调用的实现方法参数数量类型需一致,返回值类型需一致。方法名可不同。
如下
public class lambaExpression {
@Test
public void lambabds() {
lambaExpression la = new lambaExpression();
A a = la::abc;
a.a("方法调用了吧");
}
void abc(String a){
System.out.println(a);
}
}
@FunctionalInterface
interface A{
void a(String a);
}
个人理解: 使用 方法归属者::方法名 此种方式,lambda表达式创建对象时,函数接口的实现方法,就是方法归属者中的方法参数数量类型一致,返回值类型一致。方法名可不同的方法。
如上所示:la是方法归属者对象,abc是方法名,a是函数接口类型的实例对象。当调用a方法时会指向调用abc方法
3,类名::new 的方式来实例化对象
构造方法的引用 一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象
如下
public class Person {
private String firstName, lastName, job, gender;
private int salary, age;
public Person(String firstName, String lastName, String job,
String gender, int age, int salary) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
this.job = job;
this.salary = salary;
}
//get set 方法省略。。。。
}
@FunctionalInterface
interface B{
Person a(String a,String b,String c,String d,int f,int e);
}
B h = Person::new;
Person a = h.a("", "", "", "", 1, 4);
System.out.println(a.getFirstName());
System.out.println(a.getAge());
个人理解:B接口中定义了方法a,返回值是Person,方法a参数类型数量顺序需与person构造方法一致。 B h = Person::new; 创建B接口类型对象h,当h调用方法a时,实际调用的是Person的构造方法
4,forEach 循环
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1,2,3,4,5);
//1,lambda表达式 遍历直接打印list元素
list.forEach(System.out::println);
//2,lambda表达式 自定义方法体遍历打印list元素
list.forEach(element -> {
if (element % 2 == 0) {
System.out.println(element);
}
});
个人理解:
看一下forEach源码
参数Consumer接口
1,lambda表达式 遍历直接打印list元素
由上面的例子可得出 System.out::println 代表的是Consumer类型或其子类类型的实现类实例对象,调用的方法println 是经常用到的PrintStream的println方法。看一下forEach
方法当走到action.accept(elementData[i]);这一步时实际调用的就是PrintStream的println方法
2,lambda表达式 自定义方法体遍历打印list元素,此种方式由上可推出当走到action.accept(elementData[i]);时,实际调用的自己实现的lamabada表达式中的方法体