Java lambda表达式

一个用来减少代码量的函数

使用 lambda 表达式可以使代码更简洁,逻辑更紧凑,但学起来属实头秃

使用方法

格式:

1
(参数列表) -> {一些重写方法的代码};
  • (): 接口找那个抽象方法的参数列表,没有参数就空着,有参数就写出参数,多个参数使用逗号分隔
  • ->: 传递的意思,把参数传递给方法体{}
  • {}: 重写接口的抽象方法的方法体

看上去很简单,但要理解就需要点时间了

没有返回值

创建线程的时候,可以用如下代码来创建线程

1
2
3
4
5
6
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
}).start();

在创建的时候,需要传入的参数只有一个,那就是 Runnable 接口的一个实现类,这里用了多态
而且只需要重写里面的 run 方法,所以,这种情况下,不看参数也知道它需要什么参数,不看重写谁,也知道它重写的是谁
于是,这些代码就可以省略了:

1
2
3
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}).start();

有返回值

定义一个 calc 接口类,里面只有一个计算的抽象类

1
2
3
public interface calc {
int sum(int a, int b); //sum方法,返回一个整数
}

然后在主函数里面定义一个使用这个接口的方法,里面只使用了 calc 这个接口

1
2
3
4
public static void invokeCalc(int a, int b, calc c){ //需要传入两个参数和一个 calc 接口的子类对象
int ans = c.sum(a,b); //此方法调用了 calc 接口的sum方法
System.out.println(ans);
}

在 main 方法中调用 invokeCalc 方法,需要重写 calc 接口的 sum 方法,才能正确调用 invokeCalc 方法
正常的写法如下

1
2
3
4
5
6
invokeCalc(10, 20, new calc() { //实例化一个 calc 的子类对象,这里用了多态
@Override
public int sum(int a, int b) {
return a + b; //返回值
}
});

重写了 sum 方法后,再执行 invokeCalc 方法的输出语句,把答案输出

此处使用 lambda 表达式可以如下简化

1
invokeCalc(20, 20 , (int a, int b)->a + b);

前两个是参数,后面的是重写 calc 的 sum 方法
(int a, int b)表示 sum 方法的参数
-> 表示传递这两个参数到 sum 方法
a + b 就是返回的值,也即是重写 sum 方法后的返回值

更丧心病狂的省略

  • lambda 表达式的参数列表括号里的参数类型可以不写
  • 参数列表里的参数只有一个的时候,括号和参数可以都不写
  • {} 里的代码如果只有一行,无论是否有返回值,都可以省略 {},return,分号 (要省略就必须都省略)

例子:

1
2
3
4
5
6
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}).start();

//优化后
new Thread(()->System.out.println(Thread.currentThread().getName() + "新线程创建了")).start();

定义一个 Cook 类,里面只有一个 makeFood() 方法

1
2
3
public interface Cook {
public abstract void makeFood();
}

主方法中定义一个使用这个接口的方法

1
2
3
public static void invokeCook(Cook cook){
cook.makeFood();
}

使用这个方法的用法有如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
invokeCook(new Cook() {
@Override
public void makeFood() {
System.out.println("恰饭了");
}
});

//普通lambda
invokeCook(()->{
System.out.println("吃饭了");
});

//优化后
invokeCook(()-> System.out.println("开吃"));

lambda 表达式就是为了简化代码而产生的,并且应用场景比较严苛,被重写的接口必须只有一个方法,调用的函数也只能使用这个接口,这样才lambda 表达式才能根据上下文来了解需要重写哪个接口的哪个方法,为了简化代码有点丧心病狂了 (」゜ロ゜)」