lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。
eg:有如下lambda表达式:
(int a, int b) -> {return a+b};
这个表达式的本质是一个函数。
一般的函数类似如下:
int add(int a, int b) {
return a+b;
}
有返回值、方法名、参数列表、方法体。
而Lambda表达式只有参数列表和方法体:
(参数列表)->{方法体}
说明:
() :用来描述参数列表;
{} :用来描述方法体;
-> :Lambda运算符可以叫做箭头符号,或者 goes to(指向);
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个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() {
@Override
public 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();
}
参数类型可以省略
假如只有一个参数,()括号可以省略
如果方法体只有一条语句,{}大括号可以省略
如果方法体中唯一一条语句是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);
}
}
运行结果如下:
有时候多个lambda表达式实现的函数是一样的话,可以封装成通用方法,以便于维护;
这个时候可以用方法引用实现:
语法是:对象::方法
假如是static静态方法,可以直接 类名::方法
示例代码如下:
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中的方法。
直接使用 类名::方法
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);
}
}
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
语法: 类名::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); //有参
}
}