简介
Lambda 表达式是 Java 1.8 跟 Stream 机制一起推出的。Lambda 表达式极大地缩小了代码量,减少了代码的可读性。
引入 Lambda 表达式之后,Java 开始反对 把函数作为参数传递。
前置条件
应用 Lambda 表达式的前置条件,作为参数的接口必须是 函数式接口
- 首先类型必须是接口
interface
,不能是类class
。比方,抽象类就不能够。 - 函数式接口有且仅有一个未被覆写的形象办法
举例:
- Object 中办法不算
// MyRunnable 依然算是一个“函数式接口”public interface MyRunnable extends Runnable {String toString();
boolean equals(Object obj);
int hashCode();}
- 接口中的 default 办法不算
// MyRunnable2 依然算是一个“函数式接口”public interface MyRunnable2 extends Runnable {default void run2() {}}
FunctionalInterface 注解
@FunctionalInterface
能够帮忙咱们在编译期辨认出一个接口是否是“函数式接口”:
参数的传递
如果咱们有一个如下含意的“函数式接口”:
@FunctionalInterface
public interface Formatter {void format(String name, int age);
}
咱们能够结构一个测试:
public class LambdaTest {public static void main(String[] args) {print((String name, int age)-> System.out.println(String.format("name:%s age:%d", name, age)), "ziyu", 18);
}
public static void print(Formatter formatter, String name, int age) {formatter.format(name, age);
}
}
多个参数
当有多个参数时,能够抉择省略所有参数类型申明:
留神:
不能省略一部分保留一部分。(String name, age) -> System.out.println(name); 这是不非法的!
单个参数
当只有一个参数时,除了能够省略参数类型,还能够进一步省略掉括号。
编写形式
没有返回值
Runnable
就是一个罕用的“函数式接口”,它的形象办法 run()
“没有返回值”, 刚好适宜用于此处的演示。测试例子如下:
public class LambdaTest2 {public static void main(String[] args) {runIt(()->{System.out.println("123");
});
}
static void runIt(Runnable runnable) {new Thread(runnable).start();}
}
- 如果写成多行表达式,那么须要
{}
来示意代码块,且每一行代码完结时须要书写;
示意语句的完结。 - 如果代码块中只有一条语句,那么能够通过省略
{}
和;
来简写为单行表达式
有返回值
咱们定义一个 IdFactory
接口来做演示:
public interface IdFactory {String generateId();
}
咱们的示例代码如下:
import java.util.UUID;
public class LambdaTest3 {public static void main(String[] args) {String name = getId(()-> UUID.randomUUID() + "");
System.out.println(name);
}
static String getId(IdFactory factory) {return factory.generateId();
}
}
- 如果写成多行表达式,除了须要
{}
来示意代码块,和每一行代码完结时须要书写;
示意语句的完结以外,还应该在须要返回值的办法用return
来返回值。 - 如果代码块中只有一条语句,那么能够通过省略
{}
和;
以及return
来简写为单行表达式
办法援用
比方咱们要写一段代码,用来打印出残缺的加法表达式 a + b = c
,并且要求依据 a 和 b 求出 c 作为函数返回值。
首先咱们定一个“计算器”接口:
public interface Calculator {int compute(int a, int b);
}
接着咱们写一个测试用例:
public class LambdaTest3 {public static void main(String[] args) {
int a = 10;
int b = 20;
// 这里不能用 (a, b), 那样的话会产生歧义,使得编译器报错
runIt((x, y)->{System.out.print(x);
System.out.print("+");
System.out.print(y);
System.out.print("=");
System.out.println(x + y);
return x + y;
}, a, b);
}
static void runIt(Calculator calculator, int a, int b) {calculator.compute(a, b);
}
}
静态方法援用
- 在 LambdaTest2 中定一个静态方法
sum
- 应用静态方法援用
LambdaTest2::sum
- 这样在运行静态方法
runIt
中的第一行calculator.compute(a, b)
时,a
和b
会通过静态方法援用传递给静态方法sum
通过这种形式,即简化了参数的传递,也把“多行表达式”简化为了“单行表达式”
成员办法援用
new LambdaTest2()::sum
:先新建对象LambdaTest2
,并且通过该对象来应用成员变量援用
小贴士:
如果先申明变量obj
,再应用obj::sum
也是非法的。
public static void main(String[] args) {
int a = 10;
int b = 20;
LambdaTest2 obj = new LambdaTest2();
runIt(obj::sum, a, b);
}
总结
- Lambda 表达式的前置条件:必须是“函数式接口”
- 单个参数传递时,能够省略参数两端的括号。参数的类型能够一起省略。
- 编写的形式次要包含单行表达式和多行表达式
- 能够应用办法援用来把多行表达式写成单行表达式。办法援用又包含了静态方法援用和动静办法援用。