lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。
1.lambda表达式的语法
eg:有如下lambda表达式:
(int a, int b) -> {return a+b};
这个表达式的本质是一个函数。
一般的函数类似如下:
int add(int a, int b) {return a+b;
}
有返回值、方法名、参数列表、方法体。
而Lambda表达式只有参数列表和方法体:
(参数列表)->{方法体}
说明:
-
() :用来描述参数列表;
-
{} :用来描述方法体;
-
-> :Lambda运算符可以叫做箭头符号,或者 goes to(指向);
2.函数式接口
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口叫做函数式接口。
通过使用lambda表达式展示应用场景。
public class Lambda {public static void main(String[] args) {If1 if1 = ()->{System.out.println("无参无返回值");};//调用方法if1.test();If2 if2 = (int a)->{System.out.println("单个参数无返回值:a = " + a);};if2.test(2);If3 if3 = (int a, int b)->{System.out.println("两个参数无返回值:a + b = " + (a + b));};if3.test(1, 2);If4 if4 = ()->{return 4;};System.out.println("无参有返回值,返回值为:" + if4.test());If5 if5 = (int a)->{return a;};System.out.println("有参有返回值,返回值为:a = " + if5.test(5));}//无参无返回值interface If1 {void test();}//单个参数无返回值interface If2{void test(int a);}//两个参数无返回值interface If3{void test(int a, int b);}//无参有返回值interface If4{int test();}//有参有返回值interface If5{int test(int a);}
}
运行结果如图:
关于如下代码的问题:
If1 if1 = ()->{System.out.println("无参无返回值");};//调用方法if1.test();
在上述代码中,If1不是一个接口吗?为什么能够有对象if1呢?
实际上这里是使用了lambda来实现匿名内部类的作用,如下:
If1 if1 = new If1() {@Overridepublic void test() {System.out.println("无参无返回值");}};//调用方法if1.test();
而匿名内部类写成正常的实现类就是类实现If1接口然后创建if1类对象,代码如下:
//定义接口
interface If1{void test();
}
//实现了接口的类
class NiMing implements If1{void test() {System.out.println("无参数无返回值");}
}
//创建类对象
public class Test{NiMing if1 = new NiMing();
}
3.lambda表达式精简语法
-
参数类型可以省略
-
假如只有一个参数,()括号可以省略
-
如果方法体只有一条语句,{}大括号可以省略
-
如果方法体中唯一一条语句是return返回语句,那么省略大括号的同时return也要省略(只省略return,不省略整个return语句)
实例代码如下:
public class Lambda2 {public static void main(String[] args) {//无参数()括号不能省略If1 if1 = ()->{System.out.println("无参无返回值");};//调用方法if1.test();//单个参数,参数类型和()括号可以省略//方法体内单个语句{}大括号可以省略If2 if2 = a-> System.out.println("单个参数无返回值:a = " + a);if2.test(2);If3 if3 = (a, b)-> System.out.println("两个参数无返回值:a + b = " + (a + b));if3.test(1, 2);//省略return和{}大括号If4 if4 = ()->4;System.out.println("无参有返回值,返回值为:" + if4.test());If5 if5 = a->a;System.out.println("有参有返回值,返回值为:a = " + if5.test(5));}//无参无返回值interface If1 {void test();}//单个参数无返回值interface If2{void test(int a);}//两个参数无返回值interface If3{void test(int a, int b);}//无参有返回值interface If4{int test();}//有参有返回值interface If5{int test(int a);}
}
运行结果如下:
4.方法引用
有时候多个lambda表达式实现的函数是一样的话,可以封装成通用方法,以便于维护;
这个时候可以用方法引用实现:
语法是:对象::方法
假如是static静态方法,可以直接 类名::方法
4.1非静态方法的方法引用
示例代码如下:
public class Lambda3 {public static void main(String[] args) {If if1 = a -> a-2;System.out.println("if1的返回值为: " + if1.test(3));If if2 = a -> a-2;System.out.println("if2的返回值为: " + if2.test(4));}//单个参数有返回值interface If{int test(int a);}
}
可以看到两个对象调用的是同一种方法,所以可以使用方法引用来替代,代码如下:
public class Lambda3 {public static void main(String[] args) {
// If if1 = a -> a-2;
// System.out.println("if1的返回值为: " + if1.test(3));
//
// If if2 = a -> a-2;
// System.out.println("if2的返回值为: " + if2.test(4));//创建对象Lambda3 lambda3 = new Lambda3();//利用lambda表达式引用方法If if1 = lambda3::testA;System.out.println("if1的返回值为: " + if1.test(3));If if2 = lambda3::testA;System.out.println("if2的返回值为: " + if2.test(4));}public int testA(int a) {return a-2;}//单个参数有返回值interface If{int test(int a);}
}
实际上testA实现的也是接口If中的方法。
4.2静态方法的方法引用
直接使用 类名::方法
public class Lambda4 {public static void main(String[] args) {//利用lambda表达式引用方法If if1 = Lambda4::testA;System.out.println("if1的返回值为: " + if1.test(3));If if2 = Lambda4::testA;System.out.println("if2的返回值为: " + if2.test(4));}//静态方法public static int testA(int a) {return a-2;}//单个参数有返回值interface If{int test(int a);}
}
5.构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
语法: 类名::new
实例代码如下:
首先定义一个Dog类:
public class Dog {private String name;private int age;//无参构造方法public Dog(){}//有参构造方法public Dog(String name, int age) {this.name = name;this.age = age;}public String getName() {return this.name;}public int getAge() {return this.age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}
//重写toString方法public String toString() {return "Dog{" + "name='" + name + '\'' +", age=" + age + '}';}
}
然后测试构造方法引用:
public class Lambda5 {public static void main(String[] args) {
// //传统方法
// //无参
// DogService1 dog1 = () -> {
// return new Dog();
// };
// System.out.println(dog1.getDog());
// //简化版本
// DogService1 dog1 = () -> new Dog();
// System.out.println(dog1.getDog());//构造方法引用//无参DogService1 dog1 = Dog::new;System.out.println(dog1.getDog());//有参DogService2 dog2 = Dog::new;System.out.println(dog2.getDog("小汪", 1));}interface DogService1{Dog getDog(); //无参}interface DogService2{Dog getDog(String name, int age); //有参}
}