Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念。
很多JVM平台上的语言(Groovy、Scala等)从诞生之日就支持Lambda表达式,但是在Java8之前,很多开发者没有选择,只能使用匿名内部类代替Lambda表达式。
测试代码:
package com.redistext.newfeatures;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
public class Java8Test {
public static void main(String[] args) {
List stringList = Arrays.asList("5", "3", "2", "7");
//非Lambda表达式,正序排序
stringList.sort(new Comparator() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
System.out.println(stringList);
//非Lambda表达式,遍历
stringList.forEach(new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//Lambda表达式,正序排序
Arrays.asList( "3", "8", "2", "1").sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
//Lambda表达式,遍历
Arrays.asList( "3", "8", "2" ).forEach( e -> System.out.print( e + "," ) );
}
}
测试结果:
函数式接口函数式接口指的是只有一个函数的接口,这样的接口可以隐式转换为Lambda表达式。java.lang.Runnable和java.util.concurrent.Callable是函数式接口的最佳例子。在实践中,函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface(Java 库中的所有相关接口都已经带有这个注解了)。
测试代码:
package com.redistext.newfeatures;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
public class Java8Test {
public static void main(String[] args) {
Java8Test tester = new Java8Test();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> {
return a * b;
};
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
//不过有一点需要注意,默认方法和静态方法不会破坏函数式接口的定义,因此如下的代码是合法的。
static String staticMethod(){
return "staticMethod";
}
default String defaultMethod(){
return "defaultMethod";
}
}
@FunctionalInterface
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}
测试结果:
接口的默认方法和静态方法上面的测试代码中用到了接口的默认方法和静态方法,这也是java8的新特性。
在Java8之前,接口中只能包含抽象方法。那么这有什么样弊端呢?比如,想再Collection接口中添加一个spliterator抽象方法,那么也就意味着之前所有实现Collection接口的实现类,都要重新实现spliterator这个方法才行。而接口的默认方法就是为了解决接口的修改与接口实现类不兼容的问题,作为代码向前兼容的一个方法。
参考文档:
掘金
JAVA8 十大新特性详解 - bcombetter - 博客园



