一、Lambda
Java 8的最大变化是引入了Lambda(Lambda 是希腊字母 λ 的英文名称)表达式,也可称为闭包。
lambda 表达式的语法格式如下:
(parameters) -> expression
(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
关于lambda表达式的变量作用域:
- 局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
- 不允许声明一个与局部变量同名的参数或者局部变量。
二、函数式接口
函数接口是只有一个抽象方法的接口,可以有多个默认方法以及静态方法,通过Lambda表达式可以创建该接口的对象,另外使用@FunctionalInterface注解修饰,编译器会检测该类是否只有一个抽象方法或接口。Runnable以及Comparator接口就是常见的函数式接口。
以下是一个定义函数式接口的例子:
@FunctionalInterface
public interface FunctionInterfaceDemo {
String test();
// String test2();
default String test3() {
return "test3";
}
static String test4() {
return "test4";
}
}
然后可以通过lambda表达式来实现接口:
public class FunctionInterfaceTest {
public static void main(String[] args) {
// 创建匿名函数
FunctionInterfaceDemo functionInterfaceDemo1 = new FunctionInterfaceDemo() {
@Override
public String test() {
return "hello ";
}
};
System.out.println(functionInterfaceDemo1.test());
// 使用lambda替代上面的写法,效果一样
FunctionInterfaceDemo functionInterfaceDemo2 = () -> "hello";
System.out.println(functionInterfaceDemo2.test());
}
}
三、方法引用
函数式接口的实例可以通过 lambda 表达式、 方法引用、构造方法引用来创建。方法引用是 lambda 表达式的语法糖,任何用方法引用的地方都可由lambda表达式替换,但是并不是所有的lambda表达式都可以用方法引用来替换。
方法引用通过方法的名字来指向一个方法,方法引用使用一对冒号 :: 。
instanceName::methodName 对象::方法名
ClassName::staticMethodName 类名::静态方法
ClassName::MethodName 类名::普通方法
ClassName::new 类名::new 调用的构造器
以下是使用的例子:
public class MethodReferenceTest {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
test5();
}
/**
* 对象名::引用成员方法
*/
static void test1() {
LocalDateTime localDateTime = LocalDateTime.now();
Supplier<String> supplier1 = () -> localDateTime.toString();
System.out.println(supplier1.get());
Supplier<String> supplier2 = localDateTime::toString;
System.out.println(supplier2.get());
}
/**
* 类名::引用静态方法
*/
static void test2() {
Supplier<LocalDateTime> supplier1 = () -> LocalDateTime.now();
System.out.println(supplier1.get());
Supplier<LocalDateTime> supplier2 = LocalDateTime::now;
System.out.println(supplier2.get());
}
/**
* 类名::引用实例方法
*/
static void test3() {
Function<String, Integer> function = (s) -> s.length();
System.out.println(function.apply("1"));
Function<String, Integer> function2 = String::length;
System.out.println(function.apply("1"));
}
/**
* 类名::new 引用类构造器
*/
static void test4() {
Function<String, String> function1 = (s) -> new String(s);
System.out.println(function1.apply("321"));
Function<String, String> function2 = String::new;
System.out.println(function2.apply("321"));
}
/**
* 数组::new 引用数组构造器
*/
static void test5() {
Function<Integer, String[]> function1 = (len) -> new String[len];
System.out.println(function1.apply(2).length);
Function<Integer, String[]> function2 = String[]::new;
System.out.println(function2.apply(2).length);
}
}