Jdk14 都要出了,Jdk9 的新特性还不了解一下?(上)

简介: Jdk14 都要出了,Jdk9 的新特性还不了解一下?

Java 新特性系列已经从 Java 7 开始补充到 Java 9 了,每一篇的反馈都还不错。这个系列会持续更新到 Java 13 版本,然后在每个 Java 新版本发布时同步更新这个系列。你可以在文末找到这个系列的其他文章。


Java 9 中最大的亮点是 Java 平台模块化的引入,以及模块化 JDK。但是 Java 9 还有很多其他新功能,这篇文字会将重点介绍开发人员特别感兴趣的几种功能。


1.  模块化


Java 9 中的模块化是对 Java 的一次重大改进。但是模块化并不是最近才提出来的,我们经常使用的  maven 构建工具,就是典型的模块化构建工具。模块化不仅让模块命名清晰,写出高内聚低耦合的代码,更可以方便处理模块之间的调用关系。


image.png


Java 9 模块系统


在 Oracle 官方中为 Java 9 中的模块系统的定义如下:


the module, which is a named, self-describing collection of code and data. This module system.


直白翻译:模块是一个命名的,自我描述的代码和数据的集合。


Java 9 不仅支持了模块化开发,更是直接把 JDK 自身进行了模块化处理。JDK 自身的模块化可以带来很多好处,比如:


  • 方便管理,越来越大的 JDK 在模块化下结构变得更加清晰。
  • 模块化 JDK 和 JRE 运行时镜像可以提高性能、安全性、维护性。
  • 可以定制 JRE,使用更小的运行时镜像,比如网络应用不需要 swing 库,可以在打包时选择不用,减少性能消耗。
  • 清晰明了的模块调用关系,避免调用不当出来的各种问题。


上面提到了 JDK 自身的模块化,我们通过浏览 JDK 9 的目录结构也可以发现一些变化。


image.png


JDK 模块化


最明显的是在 JDK 9 中 jre 文件夹不存在了。下面是在 IDEA 中查看的 JDK 9 的依赖,命名规范的模块看起来是不是让人赏心悦目呢?


image.png


JDK 9 在 DEA (这里我放错图了,微信不支持改图)


当然,这篇文章主要介绍 Java 9 的新特性,而模块化是一个巨大改变,结合示例介绍下来篇幅会比较长,这里就不占用太多篇幅了。


模块化文章预告:如何编写一个模块化系统,如何打包让没有安装 Java 环境的系统运行编写的代码,都可以通过模块化选择运行时模块实现。我后面的文章就会通过一个模块化项目介绍到,有兴趣的可以关注我后续文章 😎。


2. 集合工厂方法


在 Java 9 中为集合的创建增加了静态工厂创建方式,也就是 of 方法,通过静态工厂 of 方法创建的集合是只读集合,里面的对象不可改变。并在不能存在 null,对于 setmap 集合,也不能存在 key 值重复。这样不仅线程安全,而且消耗的内存也更小


下面是三种集合通过静态工厂创建的方式。


// 工厂方法创建集合
List<String> stringList = List.of("a", "b", "c", "d");
Set<String> stringSet = Set.of("a", "b", "c", "d");
Map<String, Integer> stringIntegerMap = Map.of("key1", 1, "key2", 2, "key3", 3);
Map<String, Integer> stringIntegerMap2 = Map.ofEntries(Map.entry("key1", 1), Map.entry("key2", 2));
// 集合输出
System.out.println(stringList);
System.out.println(stringSet);
System.out.println(stringIntegerMap);
System.out.println(stringIntegerMap2);


得到输出结果。


[a, b, c, d]
[d, a, c, b]
{key2=2, key1=1, key3=3}
{key2=2, key1=1}


再次运行,得到输出结果。


[a, b, c, d]
[a, c, b, d]
{key3=3, key2=2, key1=1}
{key2=2, key1=1}


为什么我贴了两次运行结果呢?主要是要展示通过 of 方法创建的 setmap 集合在遍历时,在每个 JVM 周期遍历顺序是随机的,这样的机制可以发下代码中有没有对于顺序敏感的异常代码。


这种只读集合在 Java 9 之前创建是通过 Collections.unmodifiableList 修改集合操作权限实现的。


List<String> arrayList = new ArrayList<>();
arrayList.add("达西");
arrayList.add("未读代码");
// 设置为只读集合
arrayList = Collections.unmodifiableList(arrayList);


静态工厂 of 方法创建的集合还有一个特性,就是工厂内部会自由复用已有实例或者创建新的实例,所以应该避免对 of 创建的集合进行判等或者 haseCode 比较等操作。


像下面这样,创建两个 List,你会发现两个 ListhashCode 是一样的。


// 工厂可以自由创建新的实例或者复用现有实例,所以 使用 of 创建的集合,避免 == 或者 hashCode 判断操作
List<String> stringList = List.of("a", "b", "c", "d");
List<String> stringList2 = List.of("a", "b", "c", "d");
System.out.println(stringList.hashCode());
System.out.println(stringList2.hashCode());
// 输出结果
// 3910595
// 3910596


这也是使用 of 方法创建集合的优势之一,消耗更少的系统资源。这一点也体现在 of 创建的集合的数据结构实现上,有兴趣的同学可以自行研究下。


3. Stream API


Stream 流操作自从 Java 8 引入以来,一直广受好评。便捷丰富的 Stream 操作让人爱不释手,更让没看过的同事眼花缭乱,在介绍 Java 8 新特性时已经对 Stream 进行了详细的介绍,没看过的同学可以看下这篇:


还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下


当然,学习 Stream 之前要先学习 Lambda ,如果你还没有看过,也可以看下之前这篇:


还看不懂同事的代码?Lambda 表达式、函数接口了解一下


Java 9 中,又对 Stream 进行了增强,主要增加了 4 个新的操作方法:dropWhile,takeWhile,ofNullable,iterate


下面对这几个方法分别做个介绍。


  1. takeWhile: 从头开始筛选,遇到不满足的就结束了。


// takeWhile ,从头开始筛选,遇到不满足的就结束了
List<Integer> list1 = List.of(1, 2, 3, 4, 5);
List<Integer> listResult = list1.stream().takeWhile(x -> x < 3).collect(Collectors.toList());
System.out.println(listResult);
// takeWhile ,从头开始筛选,遇到不满足的就结束
List<Integer> list2 = List.of(1, 2, 3, 4, 3, 0);
List<Integer> listResult2 = list2.stream().takeWhile(x -> x < 3).collect(Collectors.toList());
System.out.println(listResult2);


输出结果。


[1, 2]
[1, 2]


  1. dropWhile: 从头开始删除,遇到不满足的就结束了。


// dropWhile ,从头开始删除,遇到不满足的就结束了
List<Integer> list1 = List.of(1, 2, 3, 4, 5);
List<Integer> listResult = list1.stream().dropWhile(x -> x < 3).collect(Collectors.toList());
System.out.println(listResult);
// dropWhile ,从头开始删除,遇到不满足的就结束
List<Integer> list2 = List.of(1, 2, 3, 4, 3, 0);
List<Integer> listResult2 = list2.stream().dropWhile(x -> x < 3).collect(Collectors.toList());
System.out.println(listResult2);


输出结果。


[3, 4, 5]
[3, 4, 3, 0]


  1. ofNullable: 创建支持全 null 的 Stream.


Stream<Integer> stream = Stream.of(1, 2, null);
stream.forEach(System.out::print);
System.out.println();
// 空指针异常
// stream = Stream.of(null);
stream = Stream.ofNullable(null);
stream.forEach(System.out::print);


输出结果。


12null


  1. iterate: 可以重载迭代器。


IntStream.iterate(0, x -> x < 10, x -> x + 1).forEach(System.out::print);


输出结果。


0123456789


Stream 增强之外,还增强了 OptionalOptional 增加了可以转换成 Stream 的方法。


Stream<Integer> s = Optional.of(1).stream();
s.forEach(System.out::print);


相关文章
|
18天前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
36 7
|
3月前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
48 3
|
2月前
|
存储 安全 Java
JDK1.8 新的特性
JDK1.8 新的特性
29 0
|
3月前
|
编解码 安全 Java
jdk8新特性-接口和日期处理
jdk8新特性-接口和日期处理
|
4月前
|
Java API
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
|
4月前
|
Oracle Java 关系型数据库
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
|
4月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
3月前
|
Java 编译器 API
JDK8新特性--lambda表达式
JDK8的Lambda表达式是Java语言的一大进步。它为Java程序提供了更多的编程方式,让代码更加简洁,也让函数式编程的概念在Java中得到了体现。Lambda表达式与Java 8的其他新特性,如Stream API、新的日期时间API一起,极大地提高了Java编程的效率和乐趣。随着时间的流逝,Java开发者对这些特性的理解和应用将会越来越深入,进一步推动Java语言和应用程序的发展。
17 0
|
4月前
|
算法 Java iOS开发
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化
|
4月前
|
XML JSON Java
JDK8到JDK26版本升级的新特性问题之在JDK 13中,字符串文本块改进字符串嵌入是如何实现的
JDK8到JDK26版本升级的新特性问题之在JDK 13中,字符串文本块改进字符串嵌入是如何实现的