Lambda表达式
简介
- Lambda表达式支持将代码块作为方法参数,允许使用更简洁的代码来创建只有一个抽象方法的接口(被称为函数式接口)的实例。
- 函数式接口:只含一个抽象方法的接口。
- Lambda表达式就相当于一个匿名方法。
- 作用:代替匿名内部类的繁琐语法。
- 部分:形参列表(允许省略形参类型,圆括号);箭头 -> ;代码块(可以省略花括号,return)
- Lambda表达式实际上会被当成一个任意类型的对象。
- Lambda表达式本质是一个函数。
(参数列表) -> {
方法体;
};
简单的Lambda表达式
interface Cal{
int add(int a, int b);
}
public class Program {
public static void main(String[] args) {
Cal c1 = new Cal() {
@Override
public int add(int a, int b) {
return a+b;
}
};
int c = c1.add(1, 2);
System.out.println(c);
}
}
interface Cal{
int add(int a, int b);
}
public class Program {
public static void main(String[] args) {
Cal c1=(int a,int b) ->{
return a+b;
};
int c=c1.add(1,2);
System.out.println(c);
}
}
Lambda表达式语法
- 搞一个案例,接口方法参数,无参,单个参数,两个参数,有返回值,没有返回值,这六种情况都罗列下:
public class Test {
public static void main(String[] args) {
I1 i1 = () -> {
System.out.println("无返回值、无参数");
};
i1.test();
I2 i2 = (int a, int b) -> {
System.out.println("无返回值,多个参数。a=" + a + ", b=" + b);
};
i2.test(2, 3);
I3 i3 = () -> {
System.out.println("有返回值、无参数");
return 100;
};
System.out.println(i3.test());
I4 i4 = (int a, int b) -> {
System.out.println("有返回值,多个参数。a=" + a + ",b=" + b);
return a + b;
};
System.out.println(i6.test(2, 4));
}
}
interface I1 {
void test();
}
interface I2 {
void test(int a, int b);
}
interface I3 {
int test();
}
interface I4 {
int test(int a, int b);
}
Lambda表达式精简语法
-
参数类型可以省略。 -
假如只有一个参数,()括号可以省略。 -
如果方法体只有一条语句,{}大括号可以省略。 -
如果方法体中唯一的语句是return返回语句,那省略大括号的同时return也可以省略。
I6 i6=(int a, int b)->{
return a+b;
};
I6 i6=(a,b)->a+b;
方法引用
- 有时候多个lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护;
- 这时候可以用方法引用实现:
语法是:对象::方法(需new一个对象) 若是static方法: 类名::方法(无需new一个对象,直接类名)
public class Program2 {
public static void main(String[] args) {
Program2 program2 = new Program2();
I5 i5 = program2::test;
System.out.println(i5.test(1));
I5 i52 = Program2::test2;
System.out.println(i52.test(1));
}
public int test(int a){
return a-2;
}
public static int test2(int a){
return a-2;
}
}
interface I5{
int test(int a);
}
构造方法引用
- 如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用;
- 语法:类名::new
public class Program3 {
public static void main(String[] args) {
DogService dogService = ()->{
return new Dog();
};
dogService.getDog();
DogService dogService2 = ()->new Dog();
dogService2.getDog();
DogService dogService3 = Dog::new;
dogService3.getDog();
DogService2 dogService21 = Dog::new;
dogService21.getDog("一二三",8);
}
}
interface DogService{
Dog getDog();
}
interface DogService2{
Dog getDog(String name,int age);
}
class Dog {
private String name;
private int age;
public Dog() {
System.out.println("无参构造方法");
}
public Dog(String name, int age) {
System.out.println("有参构造方法");
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@FunctionalInterface注解
- 这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
- 接口有且仅有一个抽象方法
- 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错
系统内置函数式接口
- Java8的推出,是以Lambda重要特性,一起推出的,其中系统内置了一系列函数式接口。
- 再jdk的java.util.function包下,有一系列的内置函数式接口:比如常用的Consumer,Comparator,Predicate,Supplier等。
Lambda表达式与匿名内部类的联系和区别
- Lambda表达式是匿名内部类的一种简化。
- 相同点:(1)都可以直接访问“effectively final”的局部变量,以及外部类的成员变量;(2)都可以直接调用从接口中继承的默认方法。
- 区别:(1)匿名内部类可以为任何接口创建实例,Lambda表达式只能为函数式接口创建实例;(2)匿名内部类可以为抽象类甚至不同类创建实例;(3)匿名内部类允许调用接口中定义的默认方法。
使用Lambda表达式调用Arrays的类方法
- Arrays类的有些方法需要Comparator、XXXOperator、XXXFunction等接口的实例,都是函数式接口,因此可以使用Lambda表达式来调用Arrays的类方法。
本文为视频课程的学习笔记,加自己一点总结。
|