特性
-
**Lambda表达式 **允许把函数作为一个方法的参数传递到方法中
-
函数式接口 有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
-
**默认方法 **接口可以有实现方法,而且不需要实现类去实现其方法。
-
**方法引用 **可以直接引用已有Java类或对象(实例)的方法或构造器
-
StreamApI对集合(Collection)对象功能的增强
-
**Date Time API **加强对日期与时间的处理
-
Optional类 解决空指针异常。
Lambda表达式
Lambda 表达式,也可称为闭包。允许把函数作为方法的参数传递到方法中。lambda由逗号分隔的参数列表、->符号、函数体三部分组成。
语法:(parameters) -> expression 或 (parameters) ->{ statements; }
public interface PersonCallBack { void callback(); } // 定义接口
public void test(String name, PersonCallBack callBack) {
System.out.println(name);
callBack.callback();
}
public static void main(String[] args) {
new Person().test("张三", () -> {
System.out.println("18");
});
}
需要声明PersonCallBack接口为函数式接口。即接口中有且仅有唯一的一个抽象方法。lambda表达式其实就实现接口并且实现了接口中的唯一的方法。
- **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
- **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
- **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
- **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,使用大括号需要指定表达式返回了一个数值。
注意:lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。@FunctionalInterface可以校验函数式接口。
在java8中新增了很多 函数式接口 。在java.util.function包下。使我们使用lambda接口更加方便。下面列举常用接口。
默认方法和静态方法
接口中使用default修饰的方法为默认方法。用static修饰的方法为静态方法。
默认方法和静态方法就是接口可以有实现方法,而且不需要实现类去实现其方法。实现类也可以实现方法进行重写。
为什么要有这个特性?
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
方法引用
方法的参数列表必须与函数式接口的抽象方法的参数列表保持一致,返回值不作要求。
-
引用方法
-
实例对象::实例方法名 instance::method
Consumer<String> consumer = System.out::println; consumer.accept("ޮ张三"); -
**类名::静态方法名 **Class::static_method
Function<Long, Long> f = Math::abs; Long result = f.apply(-3L); -
类名::实例方法名 Class::method
BiPredicate<String, String> b = String::equals; b.test("a", "b"); -
引用构造方法 Class::new
Supplier<Person> supplier = Person::new; Person person = supplier.get(); -
引用数组
Function<Integer, int[]> fun = int[]::new; int[] arr = fun.apply(10);
Optional 类
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
创建Optional对象的几个方法:
-
Optional.of(T value), 返回一个Optional对象,value不能为空,否则会出空指针异常
-
Optional.ofNullable(T value), 返回一个Optional对象,value可以为空
-
Optional.empty(),代表空
其他API
-
optional.isPresent(),是否存在值(不为空)
-
optional.ifPresent(Consumer<? super T> consumer), 如果存在值则执行consumer
-
optional.get(),获取value
-
optional.orElse(T other),如果没值则返回other
-
optional.orElseGet(Supplier<? extends T> other),如果没值则执行other并返回
-
optional.orElseThrow(Supplier<? extends X> exceptionSupplier),如果没值则执行exceptionSupplier, 并抛出异常
注意:
使用 Optional 时尽量不直接调用 Optional.get() , Optional.isPresent() 方法。 应依赖于 其他像 Optional.orElse(), Optional.orElseGet()等这样的方法.
Stream API
Date Time API
Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。
java8之前
-
非线程安全 java.util.Date 是非线程安全的,所有的日期类都是可变的
-
**设计很差 **日期/时间类的定义不一致,在java.util和java.sql的包中都有日期类。
-
**时区处理麻烦 **日期类并不提供国际化,没有时区支持
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
LocalDate类
LocalDate只持有ISO-8601格式且无时区信息的日期部分
LocalDate now = LocalDate.now(); // 2020-10-08
now = now.plusDays(2); // 2020-10-10
now = now.plusMonths(1); // 2020-11-10
now = now.minusMonths(1); // 2020-10-10
now = now.minusDays(2); // 2020-10-08
LocalDate date3 = LocalDate.of(2020, Month.DECEMBER, 12); // 2020-12-12
获取当前日期,对其进行修改
LocalTime类
LocalTime只持有ISO-8601格式且无时区信息的时间部分
LocalTime now = LocalTime.now(); // 22:10:54.613
now = now.plusMinutes(12); // 22:22:54.613
now = now.minusHours(2); // 20:22:54.613
System.out.println(now.format(DateTimeFormatter.ofPattern("HH:mm:ss"))); // 20:22:54
LocalTime date4 = LocalTime.of(22, 15, 30); // 20:15:30
LocalTime date5 = LocalTime.parse("20:15:30"); // 20:15:30
获取当前时间,对其进行修改
LocalDateTime类
LocaleDateTim把LocaleDat与LocalTime的功能合并起来
ZonedDateTime类
从指定时区的系统时钟中获取当前日期时间。
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
System.out.println(now); // 2020-10-08T07:13:54.754-07:00[America/Los_Angeles]
获取当前时区
ZoneId currentZone = ZoneId.systemDefault();
System.out.println("当期时区: " + currentZone); // 当期时区: Asia/Shanghai
Clock类
它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间
Clock shanghai = Clock.system(ZoneId.of("Asia/Shanghai"));
System.out.println(LocalDateTime.now(shanghai)); // 2020-10-08T22:15:39.999
Duration类
Duration计算两个日期差
LocalDateTime start = LocalDateTime.parse("2020-01-01 22:10:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime end = LocalDateTime.parse("2020-02-01 22:15:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Duration duration = Duration.between(start, end);
System.out.println(duration.toDays()); // 31
System.out.println(duration.toHours()); // 744