1.java8新特性
Java8 新增了非常多的特性,主要有以下几个:
Lambda 表达式:Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)
函数式接口:指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式
方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码
默认方法:默认方法就是一个在接口里面有了一个实现的方法
Stream API:新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
Optional 类:Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
Date Time API:加强对日期与时间的处理。
Nashorn, JavaScript 引擎:Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用
2.Lambda 表达式简介
Lambda 表达式,也称为闭包,是 Java 8 中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理,函数式开发者非常熟悉这些概念。
很多JVM平台上的语言(Groovy、Scala等)从诞生之日就支持 Lambda 表达式,但是 Java 开发者没有选择,只能使用匿名内部类代替Lambda表达式。
表达式语法:
(parameters) -> expression 或 (parameters) ->{ statements; }
Lambda 编程风格,可以总结为四类:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号
可选的大括号:如果主体包含了一个语句,就不需要使用大括号
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值
3.Lambda表达式的五种使用场景
第一种场景:无参,无返回值类型
/** * Lambda表达式快捷开启线程 * 第一种:无参,无返回值类型 */ @Test public void test1() { Runnable runnable = () -> System.out.println("我爱中国!"); runnable.run(); }
第二种场景:需要参数,但是没有返回值
/** * 需要参数,但是没有返回值 */ @Test public void test2() { Consumer<String> con = (String s) -> { System.out.println("s=" + s); }; con.accept("dahe"); }
场景三:类型推断
/** * 类型推断 * 数据类型可以进行省略操作,可以由编译器进行类型推断 */ @Test public void test3() { Consumer<String> con = (s) -> { System.out.println("s=" + s); }; con.accept("dahe"); }
场景四:数列表只有一个参数,可以省略括号
@Test public void test4() { Consumer<String> con = s -> { System.out.println("s=" + s); }; con.accept("dahe"); }
场景五:参数列表有多个参数,并且可以有返回值
/** * 参数列表有多个参数,并且可以有返回值 */ @Test public void test5() { Comparator<Integer> comparator = (o1, o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(comparator.compare(521, 1314));
4.函数式接口
Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念。
函数接口指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。
但是在实践中,函数式接口非常脆弱,只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface
Lambda表达式的本质:作为函数式接口的实现🎈
以下是一个函数式接口的案例:
@FunctionalInterface public interface GreetingService { void sayMessage(String message); }
5.java内置的四大函数式接口
函数式接口案例:
import org.junit.jupiter.api.Test; import java.util.function.Consumer; /** * java内置的函数式接口 */ public class FunctionalInterface { /** * 体验Consumer接口 */ @Test public void test1() { happyTime(600, money -> System.out.println("给我钱" + money)); } public void happyTime(double money, Consumer<Double> con) { con.accept(money); } }
