1.什么是Lambda表达式
Lambda 表达式是Java 8 发布的重要新特性。
Lambda 表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。
它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 语言的表达能力得到了提升。
2、Lambda表达式的语法
基本语法: (parameters) -> expression
3、什么是函数式接口
先来理解下函数式接口,因为Lambda是建立在函数式接口的基础上的。
(1)只包含一个抽象方法的接口,称为函数式接口。
(2)你可以通过 Lambda 表达式来创建该接口的对象。
(3)我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检测它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
在实际开发者有两个比较常见的函数式接口:Runnable接口,Comparator接口
4、举例:
函数式接口:
package lambda;
public interface ICac {
int cac(int a,int b);
}
package lambda;
public interface IPerson {
void show();
}
package lambda;
public interface IPerson1 {
String show(String name,String address);
}
实体类:
package lambda;
public class Person {
String name;
int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类:
package lambda;
import java.util.Arrays;
import java.util.Comparator;
public class TestDemo2 {
private static void invokecac(int a,int b,ICac iCac){
int sum = iCac.cac(a,b);
System.out.println(sum);
}
private static void invokeshow(String name,String address,IPerson1 iPerson){
String info = name+" -> "+address;
System.out.println("该学生的信息为:"+info);
}
private static void testShow(IPerson iPerson){
iPerson.show();
}
public static void main(String[] args) {
//Runnable接口的函数式接口的lambda表达式练习
new Thread(()-> System.out.println(Thread.currentThread().getName()+" lambda 表达式 : ")).start();
//IPerson接口的show()函数式接口的lambda表达式练习
testShow(()-> System.out.println("Person : show..."));
Person[] array = {
new Person("李白",28),
new Person("王安石",21),
new Person("曾巩",48),
new Person("白居易",31),
new Person("杜牧",19)
};
/**
* 1. 使用Lambda必须具有接口,且要求**接口中有且仅有一个抽象方法**。
* 无论是JDK内置的`Runnable`、`Comparator`接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
* 2. 使用Lambda必须具有**上下文推断**。
* 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
*
* > 备注:有且仅有一个抽象方法的接口,称为“**函数式接口**”。
*/
//匿名内部类,对集合中的person实例对象进行按年龄排序
Comparator<Person> comp = new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
};
Arrays.sort(array,comp);
//lambda表达式写法
Arrays.sort(array,(Person a,Person b)->{
return a.getAge() - b.getAge();
});
for(Person person:array){
System.out.println(person);
}
//抽象类ICal的函数式接口:lambda表达式
invokecac(100,100,(int c,int d)-> {
return c + d;
});
//抽象类IPerson的函数式接口的lambda接口
invokeshow("白居易","湖南岳阳",(String name,String address) -> {
return name+" -> "+address;
});
}
}
测试结果:
总结:
了解 Lambda和匿名内部类在使用上的区别
- 所需的类型不一样
匿名内部类,需要的类型可以是类,抽象类,接口
Lambda表达式,需要的类型必须是接口 - 抽象方法的数量不一样
匿名内部类所需的接口中抽象方法的数量随意
Lambda表达式所需的接口只能有一个抽象方法 - 实现原理不同
匿名内部类是在编译后会形成class
Lambda表达式是在程序运行的时候动态生成class
小结
当接口中只有一个抽象方法时,建议使用Lambda表达式,其他其他情况还是需要使用匿名内部类