JAVA基础--Lamda表达式与方法引用
什么是函数式接口:
函数式接口有且仅有一个抽象方法,可以有多个普通方法和静态方法。
Java中对函数式接口的编译约束定义了@FunctionalInterface注释;标注了@FunctionalInterface注释的接口,在编译阶段进行了抽象接口数量约束。
函数式接口常用于lamda表达式与方法引用。
什么是lamda表达式:
使用场景:
在接口当且仅有一个抽象方法时,取代匿名内部类的使用。
表达式格式:
lamda表达式本质是匿名方法,即没有方法名的方法。lamda表达式规定接口只能是函数式接口,通过实现方法的方式为函数式接口赋值。
lamda表达式格式1:
(参数名1,参数名2)->{方法体}
lamda表达式格式2:
参数唯一且方法体只有一个返回语句,可直接省略()、{}与return。
//如参数名为age,返回值为age*2时,lamda表达式如下:
age -> age*2
优点:
JDK8推出了lamda表达式可以取代大部分使用的匿名内部类,简化了代码的编写。
什么是方法引用:
使用场景:
使用lamda表达式来实现函数式接口,用到的是已存在的方法,除了调用操作无其他多余动作时,并且已存在方法参数与返回值与函数式接口中的抽象方法一致,这时可以使用方法引用来为函数式接口赋值。方法引用可以看成是一种使用已有方法的lamda表达式。
方法引用的格式:
//格式为类名::方法名,::进行类名与方法名分割,如
System.out::println
方法引用四种形式:
- 构造器引用
- 静态方法引用
- 特定类任意对象方法引用
- 特定方法的引用
构造器引用格式为Class::new
Car car = Car.create( Car::new );
静态方法引用为Class::staticMethod
final List< Car > cars = Arrays.asList( car );
cars.forEach( Car::collide );
特定类任意对象方法引用为Class::ordinaryMethod
cars.forEach( Car::repair );
特定方法的引用instance::ordinaryMethod
cars.forEach( car::follow );
示例对象类代码为:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
class Car {
//Supplier是jdk1.8的接口,这里和lamda一起使用了
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
}
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
public void repair() {
System.out.println("Repaired " + this.toString());
}
}
优点:
进一步支持lamda表达式简写,提高了代码的可读性,也使逻辑更加清晰。
lamda表达式与方法引用的作用:
JDK8推出了lamda表达式与方法引用可以取代大部分使用的匿名内部类,简化了代码的编写,也使逻辑清晰。
使用示例:
1、声明函数式接口
@FunctionInterface注释标注在接口上表示该接口是函数式接口,会在IDE编译层面即可对该接口进行函数式接口约束。不标注即失去在IDE编译层面约束。
进行约束,IDE编译层面报错的函数式接口:
进行约束,IDE编译层面正确的函数式接口:
2、声明其他类型的静态方法
要求:该静态方法形参与返回值与函数式接口形参与返回值一致
另外声明了一个形参不一致的方法用于使用对照比较。
class DemoClass {
//形参与函数式接口不符,用于使用对比
public static String DemoClassNoArgs(){
return "DemoClass1";
}
public static String DemoClassHaveArgs(String str){
return "DemoClass2 "+str;
}
}
3、声明函数式接口方法调用方法
class DemoUser{
public String use(DemoInterface demoInterface,String str){
//函数式接口调用
return demoInterface.inter(str);
}
}
4、以方法引用创建函数式接口对象
lamda表达式与方法引用创建函数式接口对象形参不一致时,IDE层面编译是立即报错。
以方法引用为例(编译报错):
lamda表达式与方法引用创建函数式接口对象形参一致时,IDE层面编译是正常。
以方法引用为例(编译正常):
5、以lamda表达式创建函数式接口对象
极简化lamda表达式创建函数式接口对象:
完整化lamda表达式创建函数式接口对象:
6、lamda表达式与方法应用执行代码与结果显示
执行代码:
public class main {
public static void main(String[] args) {
DemoUser demoUser=new DemoUser();
System.out.println("使用方法引用为函数式接口创建对象:");
String useByMethod = demoUser.use(DemoClass::DemoClassHaveArgs, "byMethod");
System.out.println(useByMethod);
System.out.println("使用简化的lamda表达式为函数式接口创建对象:");
String useByLamda = demoUser.use(demoUserArgs -> demoUserArgs, "simple");
System.out.println(useByLamda);
System.out.println("上面简化的lamda表达式复杂化的为函数式接口创建对象:");
useByLamda = demoUser.use((demoUserArgs) -> {return demoUserArgs;} , "complex");
System.out.println(useByLamda);
}
}
执行结果: