1. 接口中的默认方法与静态方法
java 8中接口可以有实现方法,方法用default关键字修饰
public interface Mother {
default String callMe(){
return "mother";
}
static String sayHello(){
return "hello";
}
}
public interface Father {
default String callMe(){
return "father";
}
static String sayHello(){
return "hello";
}
}
public class Child implements Father, Mother {
public String callMe(){
return "child";
}
}
- 当接口和子类同时拥有方法签名相同的方法时,子类的方法会覆盖父类的方法
- 当子类继承的多个接口具有方法签名相同的方法时,子类必须覆盖父类的方法
- 静态方法的修饰符只能是public
2. java 8函数式接口和Lambda表达式
几种常见的jdk自带的函数式接口介绍:
/**
* 消费型接口
*/
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
...
}
/**
* 供给型接口
*/
@FunctionalInterface
public interface Supplier<T> {
T get();
}
/**
* 函数型接口
*/
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
...
}
/**
* 断定型接口
*/
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
...
}
函数式接口只能拥有一个抽象方法,可以包含静态方法以及默认方法,@FunctionalInterface可以作用在函数式接口上方,但是加不加@FunctionalInterface对于接口是不是函数式接口没有影响,该注解知识提醒编译器去检查该接口是否仅包含一个抽象方法
Lambda表达式语法介绍:
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
//.............
return statmentM;
由于编译器可以自动推导参数类型所以可以省略参数类型:
(param1, param2, ..., paramN) -> {
statment1;
statment2;
//.............
return statmentM;
当参数为一个时可以省略():
param1 -> {
statment1;
statment2;
//.............
return statmentM;
当执行语句只有一条时可以省略大括号、return和语句结尾的分号:
param1 -> statment
3. 方法引用
方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些。方法引用是一种更简洁易懂的Lambda表达式。
注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。
方法引用的几种表示形式(摘自菜鸟教程):
package com.runoob.main;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
class Car {
//Supplier是jdk1.8的接口,这里和lamda一起使用了
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
}
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
public void repair() {
System.out.println("Repaired " + this.toString());
}
}
- 构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car ); - 静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide ); - 特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair ); - 特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
4. Optional类
Optional类是一个容器对象,可以包含null,用来解决java语言编程中经常出现的空指针异常(NullPointerException)
源码介绍:
/**
* 返回一个空的Optional对象
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* 返回一个非空Optional对象
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* 返回一个可为空的Optional对象
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* 判断容器中的值是否为空
*/
public boolean isPresent() {
return value != null;
}
/**
* 当容器中的值不为空时执行相应的逻辑
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
/**
* 过滤掉不符合条件的值
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
/**
* 对容器中的值映射返回一个新的Optional对象(可为空)
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* 对容器中的值映射返回一个新的Optional对象(不可为空)
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
/**
* 获取容器中的值,如果为空,通过自定义方法返回值
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
5. 新的时间日期API
●Instant——它代表的是时间戳
●LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周、年纪念日,入职日期等。
●LocalTime——它代表的是不含日期的时间
●LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区。
●ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
Instant使用介绍:
// Instant类似与Date Instant与Date相互转化
System.out.println(new Date().toInstant());
System.out.println(Date.from(Instant.now()));
LocalDate使用介绍:
// 当前日期 2018-12-26
System.out.println(LocalDate.now().toString());
// 日期格式化 2018-10-01
System.out.println(LocalDate.parse("2018-10-01").toString());
// 当前日期减一天 2018-12-25
System.out.println(LocalDate.now().minusDays(1));
// 当前日期加两天 2018-12-28
System.out.println(LocalDate.now().plusDays(2));
// 当前年的第多少天的日期 2018-03-19
System.out.println(LocalDate.now().withDayOfYear(78));
Period使用介绍:
// Period 计算两个日期之间的间隔 P-9M-9D
System.out.println(Period.between(LocalDate.now().plusDays(2), LocalDate.now().withDayOfYear(78)));
LocalTime使用介绍:
// 当前时间 22:41:47.567
System.out.println(LocalTime.now());
// 最小时间 最大时间 中午时间 00:00--23:59:59.999999999--12:00
System.out.println(LocalTime.MIN + "--" + LocalTime.MAX + "--" + LocalTime.NOON);
// 获取指定时间 20:20:20
System.out.println(LocalTime.of(20, 20, 20));
// 解析时间 12:12:12
System.out.println(LocalTime.parse("12:12:12"));
LocalDateTime使用介绍:
// 当前日期时间 2018-12-26T22:41:47.568
System.out.println(LocalDateTime.now().toString());
// 获取指定日期时间 2020-10-01T00:00
System.out.println(LocalDateTime.of(2020, 10, 01, 00, 00, 00));
// 获取当天最小时间 2018-12-26T00:00
System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.MIN));
// 获取当天最大时间 2018-12-26T23:59:59.999999999
System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.MAX));
// 日期时间减操作 2018-12-25T22:41:47.569
System.out.println(LocalDateTime.now().minusDays(1).toString());
// 日期时间加操作 2018-12-27T22:41:47.569
System.out.println(LocalDateTime.now().plusDays(1).toString());
// 解析时间 2018-12-01T11:11:11
System.out.println(LocalDateTime.parse("2018-12-01 11:11:11",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
Duration使用介绍:
// Duration 计算两个日期时间之间的间隔 PT48H
System.out.println(Duration.between(LocalDateTime.now().minusDays(1), LocalDateTime.now().plusDays(1)));
ZoneId、ZoneDateTime使用介绍:
// 获取亚洲的所有可用时区 Asia/Aden Asia/Aqtau Asia/Pontianak
ZoneId.getAvailableZoneIds().stream().filter(ele -> ele.startsWith("Asia")).forEach(System.out::println);
// 获取默认ZoneId对象 Asia/Shanghai
System.out.println(ZoneId.systemDefault());
// 获取指定时区 UTC
System.out.println(ZoneId.of("UTC"));
// 通过时区的简称获取全球时区对应的映射 Asia/Shanghai
System.out.println(ZoneId.SHORT_IDS.get("CTT"));
// 获取当前默认时区时间 2018-12-26T22:56:20.377+08:00[Asia/Shanghai]
System.out.println(ZonedDateTime.now());
// 获取指定时区时间 2018-12-26T22:56:20.377Z[UTC]
System.out.println(ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("UTC")));
DateTimeFormatter使用介绍:
// 时间日期格式化 -- 预定义的标注格式 2018-12-26T23:18:21.38
System.out.println(DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now()));
// 语言环境相关的格式化风格 2018-12-26 23:17:44
System.out.println(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(LocalDateTime.now()));
// 自定义格式化 2018-12-26 23-17-44
System.out.println(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss").format(LocalDateTime.now()));
// 日期格式化 2018-10-01
System.out.println(LocalDate.parse("2018-10-01").toString());
// 解析时间 12:12:12
System.out.println(LocalTime.parse("12:12:12"));
// 解析时间 2018-12-01T11:11:11
System.out.println(LocalDateTime.parse("2018-12-01 11:11:11",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
网友评论