【终极版】Java8 新特性全面介绍,强烈建议收藏(三)

简介: Java 8 已经发布很久了,很多报道表明 Java 8 是一次重大的版本升级,虽然我们的 JDK 环境也升级到1.8,但是在日常的开发过程中,使用最多的编程风格还是停留在 JDK1.7。

七、Optional 类

Java应用中最常见的bug就是空值异常。在 Java 8 之前,Google Guava 引入了 Optionals 类来解决 NullPointerException,从而避免源码被各种 null 检查污染,以便开发者写出更加整洁的代码。Java 8 也将 Optional 加入了官方库。

Optional 提供了一些有用的方法来避免显式的 null 检查,我们可以通过以下实例来更好的了解 Optional 类的使用!

public class OptionalTester {
    public static void main(String[] args) {
        OptionalTester tester = new OptionalTester();
        Integer value1 = null;
        Integer value2 = new Integer(10);
        // Optional.ofNullable - 允许传递为 null 参数
        Optional<Integer> a = Optional.ofNullable(value1);
        // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
        Optional<Integer> b = Optional.of(value2);
        System.out.println(tester.sum(a,b));
    }
    public Integer sum(Optional<Integer> a, Optional<Integer> b){
        // Optional.isPresent - 判断值是否存在
        System.out.println("第一个参数值存在: " + a.isPresent());
        System.out.println("第二个参数值存在: " + b.isPresent());
        // Optional.orElse - 如果值存在,返回它,否则返回默认值
        Integer value1 = a.orElse(new Integer(0));
        //Optional.get - 获取值,值需要存在
        Integer value2 = b.get();
        return value1 + value2;
    }
}

如果想要了解更多用法,可以参考这篇文章:Optional 官方 API

八、新的日期时间 API

Java 8引入了新的 Date-Time API(JSR 310) 来改进时间、日期的处理!

在旧版的 Java 中,日期时间 API 存在诸多问题,例如:

  • 非线程安全:java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差:Java的日期/时间类的定义并不一致,在java.utiljava.sql的包中都有日期类,此外用于格式化和解析的类被定义在java.text包中。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦:日期类并不提供国际化,没有时区支持,因此 Java 引入了java.util.Calendarjava.util.TimeZone类,但他们同样存在上述所有的问题。

因为上面这些原因,诞生了第三方库Joda-Time,可以替代 Java 的时间管理 API 。

Java 8 中新的时间和日期管理 API 深受Joda-Time影响,并吸收了很多Joda-Time的精华,新的java.time包包含了所有关于日期、时间、时区、Instant(跟日期类似但是精确到纳秒)、duration(持续时间)和时钟操作的类。

新设计的 API 认真考虑了这些类的不变性,如果某个实例需要修改,则返回一个新的对象。

接下来看看java.time包中的关键类和各自的使用例子。

8.1、Clock类

Clock类使用时区来返回当前的纳秒时间和日期。Clock可以替代System.currentTimeMillis()TimeZone.getDefault(),实例如下:

final Clock clock = Clock.systemUTC();
System.out.println( clock.instant() );
System.out.println( clock.millis() );

输出结果是

2021-02-24T12:24:54.678Z
1614169494678

8.2、LocalDate、LocalTime 和 LocalDateTime类

LocalDate、LocalTime 和 LocalDateTime 类,都是用于处理日期时间的 API,在处理日期时间时可以不用强制性指定时区。

8.2.1、LocalDate

LocalDate 仅仅包含ISO-8601日历系统中的日期部分,实例如下:

//获取当前日期
final LocalDate date = LocalDate.now();
//获取指定时钟的日期
final LocalDate dateFromClock = LocalDate.now( clock );
System.out.println( date );
System.out.println( dateFromClock );

输出结果:

2021-02-24
2021-02-24
8.2.2、LocalTime

LocalTime 仅仅包含该日历系统中的时间部分,实例如下:

//获取当前时间
final LocalTime time = LocalTime.now();
//获取指定时钟的时间
final LocalTime timeFromClock = LocalTime.now( clock );
System.out.println( time );
System.out.println( timeFromClock );

输出结果:

20:36:16.315
20:36:16.315
8.2.3、LocalDateTime

LocalDateTime 类包含了 LocalDate 和 LocalTime 的信息,但是不包含 ISO-8601 日历系统中的时区信息,实例如下:

//获取当前日期时间
final LocalDateTime datetime = LocalDateTime.now();
//获取指定时钟的日期时间
final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );
System.out.println( datetime );
System.out.println( datetimeFromClock );

输出结果:

2021-02-24T20:38:13.633
2021-02-24T20:38:13.633

8.3、ZonedDateTime类

如果你需要特定时区的信息,则可以使用 ZoneDateTime,它保存有 ISO-8601 日期系统的日期和时间,而且有时区信息,实例如下:

// 获取当前时间日期
final ZonedDateTime zonedDatetime = ZonedDateTime.now();
//获取指定时钟的日期时间
final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );
//获取纽约时区的当前时间日期
final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of("America/New_York") );
System.out.println( zonedDatetime );
System.out.println( zonedDatetimeFromClock );
System.out.println( zonedDatetimeFromZone );

输出结果:

2021-02-24T20:42:27.238+08:00[Asia/Shanghai]
2021-02-24T12:42:27.238Z
2021-02-24T07:42:27.241-05:00[America/New_York]

8.4、Duration类

Duration类,它持有的时间精确到秒和纳秒。利用它我们可以很容易得计算两个日期之间的不同,实例如下:

final LocalDateTime from = LocalDateTime.of( 2020, Month.APRIL, 16, 0, 0, 0 );
final LocalDateTime to = LocalDateTime.of( 2021, Month.APRIL, 16, 23, 59, 59 );
//获取时间差
final Duration duration = Duration.between( from, to );
System.out.println( "Duration in days: " + duration.toDays() );
System.out.println( "Duration in hours: " + duration.toHours() );

输出结果:

Duration in days: 365
Duration in hours: 8783

九、Base64

在 Java 7中,我们经常需要使用第三方库就可以进行 Base64 编码。

在 Java 8中,Base64 编码已经成为 Java 类库的标准,实例如下:

public class Tester {
    public static void main(String[] args) {
        final String text = "Base64 finally in Java 8!";
        final String encoded = Base64.getEncoder().encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
        System.out.println( encoded );
        final String decoded = new String(Base64.getDecoder().decode( encoded ), StandardCharsets.UTF_8 );
        System.out.println( decoded );
    }
}

输出结果:

QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ==
Base64 finally in Java 8!

新的 Base64API 也支持 URL 和 MINE 的编码解码,详情可以查看具体类方法。

十、Nashorn JavaScript 引擎

从 JDK 1.8 开始,Nashorn 取代 Rhino(JDK 1.6, JDK1.7) 成为 Java 的嵌入式 JavaScript 引擎。它使用基于 JSR 292 的新语言特性,将 JavaScript 编译成 Java 字节码。

与先前的 Rhino 实现相比,这带来了 2 到 10 倍的性能提升,实例如下:

public class JavaScriptTester {
    public static void main(String[] args) {
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
        String name = "Hello World";
        try {
            nashorn.eval("print('" + name + "')");
        }catch(ScriptException e){
            System.out.println("执行脚本错误: "+ e.getMessage());
        }
    }
}

输出结果:

Hello World

在实际的开发中,使用的比较少!

十一、总结

Java 8 使得 Java 平台又前进了一大步,尤其是 Stream 流操作,使用的时候非常的爽,整个代码看起来也更加的简洁、直观、舒服!

现在 JDK 已经更新到13了,在后期,小编也会陆续给大家介绍新特性,欢迎点赞吐槽!

相关文章
|
2月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
74 2
|
2月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
43 3
|
2月前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
34 2
|
3天前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
12天前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
31 5
|
1月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
31 4
|
2月前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
82 3
|
2月前
|
存储 安全 Java
Java Map新玩法:深入探讨HashMap和TreeMap的高级特性
【10月更文挑战第19天】Java Map新玩法:深入探讨HashMap和TreeMap的高级特性,包括初始容量与加载因子的优化、高效的遍历方法、线程安全性处理以及TreeMap的自然排序、自定义排序、范围查询等功能,助你提升代码性能与灵活性。
28 2
|
2月前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
27 2
|
2月前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
40 2