关于剩余Java8新特性知识点总结,包含:默认方法、Optional、CompletableFuture、时间相关。

默认方法

默认方法皆在帮助Java新功能可以兼容低版本JDK已开发的程序。 比如说,给一个低版本已存在的接口增加新方法,那原来实现该接口的类是不是都需要实现新的方法,这非常不友好,也不利于项目JDK版本的升级,所以引入新的规则默认方法。

使用方法也非常简单,只需要在接口方法前加上关键字default,然后再将其实现之就好了。

public interface Parent {
default void hello(){
System.out.println("hello");
}
}
public class Son implements Parent {
public static void main(String[] args) {
Son son = new Son();
son.hello();
}
}

默认方法很好的解决了菱形继承的问题,虽然Java是单继承,一般情况下不会出现这种问题,但是别忘了Java除了继承,还有实现,假设有一下这种情况。

Son实现了Parent、Parent1,Parent和Parent1都继承了GrandParent,而GrandParent中有一个抽象方法hello,然后Son就会报错。而如果将GrandParent中的方法改成默认方法,这个为你就解决了。

//这种方式,Son会报错
public interface GrandParent {
void hello();
}
//这种方式就ok了
public interface GrandParent {
default void hello(){
System.out.println("hello");
}
}

其实有了默认方法,一个Java类可以实现N多个接口,无论它们多么错综复杂。但是为了代码层次,最好使用代理模式,提前实现一层代理类封装好所有的接口,真正继承的类再去继承代理类,这样使用起来就会很舒服了。

Optional

但凡写过Java的同学,一定知道null的存在,null是那些从未定义对象的指向。为了避免NullPointerException的出现,代码中要加大量的if判断。为了让这种冗余的无意义的代码消失,为了更加符合Java设计哲学,Optional应运而生。

Optional就是将用户创建的对象再进一步封装,使用户对象只是Optional对象的一部分,这样对于开发人员层面来说,就不会直接操作未定义的对象了。

创建Optional

假设我们的用户类就是上一节中的Son。创建一个包含Son对象的Optional,并且Son对象目前指向为null。使用静态方法Optional.empty()

Optional<Son> optCar = Optional.empty();

接着将存在的用户对象Son放到Optional中。

Son son = new Son();
Optional<Son> sonOptional = Optional.of(son);

不过使用Optional.of需要保证参数必须不为null,否则就会抛出NullPointerException 异常,为了解决这个问题,可以使用下面这个方法。

Optional<Son> sonOptional = Optional.ofNullable(son);

Optional结合流操作

不仅仅是判空问题,Optional可以天然的和Stream结合。为了方便,我们给Son类增加属性name、age。

@Data
public class Son implements Parent,Parent2 {
private String name;
private Integer age;
}

现在假设我们需要知道son的name,首先需要判断son是否为空,再使用方法son.getName()对吧。然而有了Optional我们可以使用map这么写。

//原始写法
Son son = null;
if(Objects.nonNull()){
String name = son.getName();
}
//新写法
Son son = null;
Optional<Son> sonOptional = Optional.of(son);
Optional<String> name = sonOptional.map(Son::getName);

值得一提的是通过Stream操作转化来的对象还是Optional,只不过泛型变成了预期值类型。

Optional嵌套问题

如果看过我上篇写的Stream的博客,那么除了map,你一定还记得flatMap , flatMap 可以合并Stream,同样的 flatMap 可以将多个嵌套的Optional进行合并。下面举个例子说明一下,为了说明问题新建两个类Computer、CPU,显而易见CPU是Computer的一部分。我们需要知道某品牌电脑CPU的生产厂家。

@Data
public class CPU {
private String name;
private String manufacturers;
}
@Data
public class Computer {
private String name;
private Optional<CPU> cpu;
}

首先使用map看一下效果。

Optional<Computer> optionalComputer = Optional.of(computer);
Optional<String> stringOptional = optionalComputer
.map(Computer::getCpu)
.map(CPU::getManufacturers);//别说运行了,这行编译失败
System.out.println(stringOptional.get());

第4行编译失败,那是因为经历第3行,此时对象的结构为Optional<Optional<CPU>>,此时的泛型是Optional<CPU>,无法直接调用CPU::getManufacturers

所以就需要使用flatMap 将两层Optional合并。

Optional<Computer> optionalComputer = Optional.of(computer);
Optional<String> stringOptional = optionalComputer
.flatMap(Computer::getCpu)
.map(CPU::getManufacturers);

ok,完美执行了。当然了,Stream中有很多方法这里都适用,比如filter。

Optional数据读取

最直接的方法就是get(),但是get()方法需要提前判空,如果用户对象(就是泛型类的对象)为null,get()方法就会报错。

stringOptional.get()

当然,你要执意使用get()方法,Java也提供了更友好的方法orElse(),这个方法可以当对象是空的时候,给一个默认值。

stringOptional.orElse("juejin")

对于orElse(),还有一个升级版本的方法orElseGet(),是orElse()延时版本,当只有使用默认值的时候,才会运算orElseGet()的参数,这样就避免了默认值是耗时操作影响性能。

stringOptional.orElseGet(()->"juejin")

如果你想在对象不存在的时候,抛出一个异常,就可以使用方法orElseThrow()

stringOptional.orElseThrow(Exception::new)

还有一个非常好用的方法ifPresent(),这个方法可以判断对象是否存在。

if (stringOptional.isPresent()){
System.out.println("stringOptional.isPresent()");
}

CompletableFuture

写过一篇《强大的CompletableFuture》

新的日期API

虽说现在有很多成型的第三方工具包,例如Hutool。处理时间问题多了很多选择,但是JDK本身的方法,不仅提供了某种意义上的最佳实践,还让代码侵入性几乎为零。

LocalDate 和 LocalTime

相信很多使用过Java8的小伙伴都用过LocalDateTime,没错,就是LocalDate和LocalTime 的结合形式,分别控制着年月日、时分秒。

LocalDate localDate = LocalDate.of(2019,11,24);
localDate.getYear();
localDate.getMonth();
localDate.getDayOfYear();
LocalTime localTime = LocalTime.of(18,40,03);
localTime.getHour();
localTime.getMinute();
localTime.getSecond();

这两个方法比较简单,可以灵活的对年月日时分秒进行读取和操作。然而真正使用多的是他们的结合版本LocalDateTime

Instant

这个类可以获取机器时间,就是从1970年开始计算的时间,举例获取时间戳。

Instant instant = Instant.now();
System.out.println(instant.getEpochSecond());

当然getEpochSecond()这个方法还可以传参数,相对于当前时间位移一定的时间间隔。

Duration 或 Period

Duration可以获取两个时间之间的间隔。

Duration d1 = Duration.between(time1, time2);
Duration d1 = Duration.between(dateTime1, dateTime2);
Duration d2 = Duration.between(instant1, instant2);

其中参数可以是 LocalTimes 、 LocalDateTimes 、 Instant。以上可以计算秒和纳秒之间的大小。

如果需要计算年、月、日之间的时间间隔,就需要用Period

Period tenDays = Period.between(LocalDate.of(2014, 3, 8),
LocalDate.of(2014, 3, 18));

时间操作

就拿LocalDateTimes举例吧,这个用的最多,新的时间类型可以快捷的对时间进行修改。

LocalDateTime localDateTime = LocalDateTime.now();
//直接修改时间,不对原始数据操作,生成新的对象。
localDateTime.withHour(1).withMonth(1);
//通过位移修改时间,不对原始数据操作,生成新的对象。
localDateTime.plusDays(12);
localDateTime.plusMinutes(33);

TemporalAdjuster

除了显示的修改时间,还可以用JDK提供的一些提前定义好的方法。

import static java.time.temporal.TemporalAdjusters.*;//注意需要这么导入
LocalDate date1 = LocalDate.of(2019, 11, 24);
System.out.println(date1);//2019-11-24
LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY));
System.out.println(date2);//2019-11-24
LocalDate date3 = date2.with(lastDayOfMonth());
System.out.println(date3);//2019-11-30

更多操作见下表

DateTimeFormatter

这个不必多说,将事件类型转化成String类型时,需要的样式格式。

LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:SS", Locale.CHINA);
System.out.println(localDateTime.format(dateTimeFormatter));
//2019-11-24 19:41:77

ZoneId

处理不同的时区,ZoneId 类替代了原来的 TimeZone 类。

LocalDateTime localDateTime = LocalDateTime.now();
ZoneId romeZone = ZoneId.of("Europe/Rome");
ZoneId shangHaiZone = ZoneId.of("Asia/Shanghai");
System.out.println(localDateTime.atZone(romeZone));
System.out.println(localDateTime.atZone(shangHaiZone));
//2019-11-24T19:52:13.105+01:00[Europe/Rome]
//2019-11-24T19:52:13.105+08:00[Asia/Shanghai]

唯一不爽的是ZoneId.of()参数是字符串(大洲/城市),没有枚举类,需要开发人员手动输入。

我的公众号

我的公众号用于博客同步。

再来看看Java的新特性——其他新特性的更多相关文章

  1. Java Development Kit(JDK) 8 新特性(简述)

    一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法. 示例如下: interface Formula { calcul ...

  2. Java高新技术 JDK1.5之新特性

      Java高新技术  JDK1.5的新特性 知识概要:                 (1)静态导入 (2)可变参数 (3)增强for循环 (4)基本数据类型的自动拆箱和装箱 静态导入     ...

  3. Java 10 的 10 个新特性,将彻底改变你写代码的方式!

    Java 9才发布几个月,很多玩意都没整明白,现在Java 10又快要来了.. 这时候我真尼玛想说:线上用的JDK 7 甚至JDK 6,JDK 8 还没用熟,JDK 9 才发布不久不知道啥玩意,JDK ...

  4. Java9发布回顾Java 8的十大新特性

    java9已经在北京时间9月22日正式发布,开发者可以在oracle jdk官网上下载到最新的jdk9. 今天,我们先来一起复习一下2014年发布的Java 8的十大新特性.先来喝杯java~~~ 按 ...

  5. Java基础20:Java8新特性终极指南

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  6. Java 9的14个新特性总结

    Java 9 包含了丰富的特性集.虽然Java 9没有新的语言概念,但是有开发者感兴趣的新的API和诊断命令. 我们将快速的,着重的浏览其中的几个新特性:  模块化系统–Jigsaw 项目 模块化是一 ...

  7. Java学习:JDK8的新特性

    Java学习:JDK8的新特性 一.十大特性 Lambda表达式 Stream函数式操作流元素集合 接口新增:默认方法与静态方法 方法引用,与Lambda表达式联合使用 引入重复注解 类型注解 最新的 ...

  8. Java 10 的 10 个新特性,你颤抖了吗?

    Java 9才发布几个月,很多玩意都没整明白,现在Java 10又快要来了.. 这时候我真尼玛想说:线上用的JDK 7 甚至JDK 6,JDK 8 还没用熟,JDK 9 才发布不久不知道啥玩意,JDK ...

  9. Java 10的10个新特性,将彻底改变你写代码的方式!

    Java 9才发布几个月,很多玩意都没整明白,现在Java 10又快要来了.. 这时候我真尼玛想说:线上用的JDK 7 甚至JDK 6,JDK 8 还没用熟,JDK 9 才发布不久不知道啥玩意,JDK ...

  10. Java 各个版本中的新特性

    新特性你知道多少? Java 8 Lambda 表达式 接口增加默认方法等 方法引用 流 Stream Java 9 模块系统 交互式工具jshell .of() 创建不可变集合 接口支持私有方法 更 ...

随机推荐

  1. Java基础——HashTable源码分析

    HashTable是基于哈希表的Map接口的同步实现 HashTable中元素的key是唯一的,value值可重复 HashTable中元素的key和value不允许为null,如果遇到null,则返 ...

  2. 查询内核符号链接的信息的API

    NtOpenSymbolicLinkObject和NtQuerySymbolicLinkObject获取指定符号链接的信息 版权声明:本文为博主原创文章,未经博主允许不得转载.

  3. CSS 宽,高,背景设置

    width 宽,height 高,background 背景:背景色 background-color:颜色值--英文单词/十六进制/rgb:背景图 background-image:url(‘图片路 ...

  4. HashMap面试总结

    作者:孤独烟 出处: http://rjzheng.cnblogs.com/ 文章由点及线再及面,写的非常好.修改部分内容 (1) HashMap的实现原理 看过HashMap源码吗,知道原理吗? h ...

  5. Java 创建对象的几种方式

    转自https://www.cnblogs.com/wxd0108/p/5685817.html 作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而 ...

  6. Unity3D一些基本的概念和一些基本操作

    场景:整个游戏由场景组成,一个游戏至少要有一个场景,如果把所有的游戏画面放在一个场景里也是可以的,如果游戏非常非常的大,如果所有的东西都放到一个场景里那么结构就不是那么清晰了而且处理起来就会麻烦一些, ...

  7. Python 安装gevent,在导入gevent之后就报错了

    错误信息如下 RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected ...

  8. javascript函数柯里化初探

    // 柯里化之前 function add(x,y,z){ return x+y+z; } add(1,2,3) // 6 // 柯里化之后 function curryAdd(x){ return ...

  9. ZJNU 2353 - UNO

    大模拟,但是题目好像有些地方表述不清 根据UNO在初中曾被别人虐了很久很久的经历 猜测出了原本的题意 本题中的+2虽然有颜色,但是也可以当作原UNO游戏中的+4黑牌 即在某人出了+2后,可以出不同颜色 ...

  10. iview checkbox demo(文档改写)

    <template> <div class="content"> <div style="border-bottom: 1px solid ...