mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-20 22:17:09 +08:00
[feat]java9 新特性完善
This commit is contained in:
parent
d5d61b303c
commit
b46a3c382a
@ -1,32 +1,161 @@
|
||||
大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成。Java 8新特性见这里:[Java8新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。
|
||||
Java 8 新特性见这里:[Java8 新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。
|
||||
|
||||
*Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!*
|
||||
_Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!_
|
||||
|
||||
## Java9
|
||||
|
||||
发布于 2017 年 9 月 21 日 。作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如集合、Stream 流
|
||||
发布于 2017 年 9 月 21 日 。作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如集合、Stream 流
|
||||
|
||||
### Java 平台模块系统
|
||||
|
||||
Java 平台模块系统,也就是 Project Jigsaw,把模块化开发实践引入到了 Java 平台中。在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。
|
||||
Java 平台模块系统是[Jigsaw Project](https://openjdk.java.net/projects/jigsaw/)的一部分,把模块化开发实践引入到了 Java 平台中,可以让我们的代码可重用性更好!
|
||||
|
||||
Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 module-info.class 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。
|
||||
什么是模块系统?官方的定义是:A uniquely named, reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor.
|
||||
|
||||
简单来说,你可以将一个模块看作是一组唯一命名、可重用的包、资源和模块描述文件(module-info.java)。
|
||||
|
||||
任意一个 jar 文件,只要加上一个 模块描述文件(module-info.java),就可以升级为一个模块。
|
||||
|
||||

|
||||
|
||||
在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。
|
||||
|
||||
我们可以通过 exports 关键词精准控制哪些类可以对外开放使用,哪些类只能内部使用。
|
||||
|
||||
```java
|
||||
module my.module {
|
||||
//exports 公开指定包的所有公共成员
|
||||
exports com.my.package.name;
|
||||
}
|
||||
|
||||
module my.module {
|
||||
//exports…to 限制访问的成员范围
|
||||
export com.my.package.name to com.specific.package;
|
||||
}
|
||||
```
|
||||
|
||||
Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 `module-info.java` 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。
|
||||
|
||||
想要深入了解 Java 9 的模块化,参见:
|
||||
|
||||
- [Project Jigsaw: Module System Quick-Start Guide](https://openjdk.java.net/projects/jigsaw/quick-start)
|
||||
- [Java 9 Modules: part 1](https://stacktraceguru.com/java9/module-introduction)
|
||||
|
||||
### Jshell
|
||||
|
||||
jshell 是 Java 9 新增的一个实用工具。为 Java 提供了类似于 Python 的实时命令行交互工具。
|
||||
|
||||
在 Jshell 中可以直接输入表达式并查看其执行结果
|
||||
在 Jshell 中可以直接输入表达式并查看其执行结果。
|
||||
|
||||
### 集合、Stream 和 Optional
|
||||

|
||||
|
||||
- 增加 了 `List.of()`、`Set.of()`、`Map.of()` 和 `Map.ofEntries()`等工厂方法来创建不可变集合,比如`List.of("Java", "C++");`、`Map.of("Java", 1, "C++", 2)`;(这部分内容有点参考 Guava 的味道)
|
||||
- `Stream` 中增加了新的方法 `ofNullable`、`dropWhile`、`takeWhile` 和 `iterate` 方法。`Collectors` 中增加了新的方法 `filtering` 和 `flatMapping`
|
||||
- `Optional` 类中新增了 `ifPresentOrElse`、`or` 和 `stream` 等方法
|
||||
### 集合增强
|
||||
|
||||
增加 了 `List.of()`、`Set.of()`、`Map.of()` 和 `Map.ofEntries()`等工厂方法来创建不可变集合(这部分内容有点参考 Guava 的味道)
|
||||
|
||||
```java
|
||||
List.of("Java", "C++");
|
||||
Set.of("Java", "C++");
|
||||
Map.of("Java", 1, "C++", 2)`;
|
||||
```
|
||||
|
||||
`Collectors` 中增加了新的方法 `filtering()` 和 `flatMapping()`。
|
||||
|
||||
`Collectors` 的 `filtering()` 方法类似于 `Stream` 类的 `filter()` 方法,都是用于过滤元素。
|
||||
|
||||
> Java 8 为 `Collectors` 类引入了 `groupingBy` 操作,用于根据特定的属性将对象分组。
|
||||
|
||||
```java
|
||||
List<String> list = List.of("x","www", "yy", "zz");
|
||||
Map<Integer, List<String>> result = list.stream()
|
||||
.collect(Collectors.groupingBy(String::length,
|
||||
Collectors.filtering(s -> !s.contains("z"),
|
||||
Collectors.toList())));
|
||||
|
||||
System.out.println(result); // {1=[x], 2=[yy], 3=[www]}
|
||||
```
|
||||
|
||||
### Stream & Optional 增强
|
||||
|
||||
`Stream` 中增加了新的方法 `ofNullable()`、`dropWhile()`、`takeWhile()` 以及 `iterate()` 方法的重载方法。
|
||||
|
||||
Java 9 中的 `ofNullable()` 方 法允许我们创建一个单元素的 `Stream`,可以包含一个非空元素,也可以创建一个空 `Stream`。 而在 Java 8 中则不可以创建空的 `Stream` 。
|
||||
|
||||
```java
|
||||
Stream<String> stringStream = Stream.ofNullable("Java");
|
||||
System.out.println(stringStream.count());// 1
|
||||
Stream<String> nullStream = Stream.ofNullable(null);
|
||||
System.out.println(nullStream.count());//0
|
||||
```
|
||||
|
||||
`takeWhile()` 方法可以从 `Stream` 中依次获取满足条件的元素,直到不满足条件为止结束获取。
|
||||
|
||||
```java
|
||||
List<Integer> integerList = List.of(11, 33, 66, 8, 9, 13);
|
||||
integerList.stream().takeWhile(x -> x < 50).forEach(System.out::println);// 11 33
|
||||
```
|
||||
|
||||
`dropWhile()` 方法的效果和 `takeWhile()` 相反。
|
||||
|
||||
```java
|
||||
List<Integer> integerList2 = List.of(11, 33, 66, 8, 9, 13);
|
||||
integerList2.stream().dropWhile(x -> x < 50).forEach(System.out::println);// 66 8 9 13
|
||||
```
|
||||
|
||||
`iterate()` 方法的新重载方法提供了一个 `Predicate` 参数 (判断条件)来决定什么时候结束迭代
|
||||
|
||||
```java
|
||||
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
|
||||
}
|
||||
// 新增加的重载方法
|
||||
public static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
两者的使用对比如下,新的 `iterate()` 重载方法更加灵活一些。
|
||||
|
||||
```java
|
||||
// 使用原始 iterate() 方法输出数字 1~10
|
||||
Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);
|
||||
// 使用新的 iterate() 重载方法输出数字 1~10
|
||||
Stream.iterate(1, i -> i <= 10, i -> i + 1).forEach(System.out::println);
|
||||
```
|
||||
|
||||
`Optional` 类中新增了 `ifPresentOrElse()`、`or()` 和 `stream()` 等方法
|
||||
|
||||
`ifPresentOrElse()` 方法接受两个参数 `Consumer` 和 `Runnable` ,如果 `Optional` 不为空调用 `Consumer` 参数,为空则调用 `Runnable` 参数。
|
||||
|
||||
```java
|
||||
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
|
||||
|
||||
Optional<Object> objectOptional = Optional.empty();
|
||||
objectOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Empty!!!"));// Empty!!!
|
||||
```
|
||||
|
||||
`or()` 方法接受一个 `Supplier` 参数 ,如果 `Optional` 为空则返回 `Supplier` 参数指定的 `Optional` 值。
|
||||
|
||||
```java
|
||||
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
|
||||
|
||||
Optional<Object> objectOptional = Optional.empty();
|
||||
objectOptional.or(() -> Optional.of("java")).ifPresent(System.out::println);//java
|
||||
```
|
||||
|
||||
### String 存储结构变更
|
||||
|
||||
JDK 8 及之前的版本,`String` 一直是用 `char[]` 存储。在 Java 9 之后,`String` 的实现改用 `byte[]` 数组存储字符串。
|
||||
|
||||
### 进程 API
|
||||
|
||||
Java 9 增加了 `ProcessHandle` 接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程
|
||||
Java 9 增加了 `ProcessHandle` 接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程。
|
||||
|
||||
```java
|
||||
System.out.println(ProcessHandle.current().pid());
|
||||
System.out.println(ProcessHandle.current().info());
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 平台日志 API 和服务
|
||||
|
||||
@ -41,21 +170,34 @@ Java 9 允许为 JDK 和应用配置同样的日志实现。新增了 `System.Lo
|
||||
|
||||
### 变量句柄
|
||||
|
||||
- 变量句柄是一个变量或一组变量的引用,包括静态域,非静态域,数组元素和堆外数据结构中的组成部分等
|
||||
- 变量句柄的含义类似于已有的方法句柄`MethodHandle`
|
||||
- 由 Java 类`java.lang.invoke.VarHandle` 来表示,可以使用类 `java.lang.invoke.MethodHandles.Lookup` 中的静态工厂方法来创建 `VarHandle` 对 象
|
||||
变量句柄是一个变量或一组变量的引用,包括静态域,非静态域,数组元素和堆外数据结构中的组成部分等
|
||||
|
||||
变量句柄的含义类似于已有的方法句柄 `MethodHandle` ,由 Java 类 `java.lang.invoke.VarHandle` 来表示,可以使用类 `java.lang.invoke.MethodHandles.Lookup` 中的静态工厂方法来创建 `VarHandle` 对象。
|
||||
|
||||
`VarHandle` 的出现替代了 `java.util.concurrent.atomic` 和 `sun.misc.Unsafe` 的部分操作。并且提供了一系列标准的内存屏障操作,用于更加细粒度的控制内存排序。在安全性、可用性、性能上都要优于现有的 API。
|
||||
|
||||
### 改进方法句柄(Method Handle)
|
||||
|
||||
- 方法句柄从 Java7 开始引入,Java9 在类`java.lang.invoke.MethodHandles` 中新增了更多的静态方法来创建不同类型的方法句柄
|
||||
方法句柄从 Java7 开始引入,Java9 在类`java.lang.invoke.MethodHandles` 中新增了更多的静态方法来创建不同类型的方法句柄。
|
||||
|
||||
### 接口私有方法
|
||||
|
||||
Java 9 允许在接口中使用私有方法。
|
||||
|
||||
```java
|
||||
public interface MyInterface {
|
||||
private void methodPrivate(){
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 其它新特性
|
||||
|
||||
- **接口私有方法** :Java 9 允许在接口中使用私有方法
|
||||
- **try-with-resources 增强** :在 try-with-resources 语句中可以使用 effectively-final 变量(什么是 effectively-final 变量,见这篇文章 [https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html](https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html))
|
||||
- **类 `CompletableFuture` 中增加了几个新的方法(`completeAsync` ,`orTimeout` 等)**
|
||||
- **Nashorn 引擎的增强** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性
|
||||
- **I/O 流的新特性** :增加了新的方法来读取和复制 InputStream 中包含的数据
|
||||
- 类 `CompletableFuture` 中增加了几个新的方法(`completeAsync` ,`orTimeout` 等)
|
||||
- **Nashorn 引擎的增强** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性(Java 11 中已经被弃用)。
|
||||
- **I/O 流的新特性** :增加了新的方法来读取和复制 `InputStream` 中包含的数据
|
||||
- **改进应用的安全性能** :Java 9 新增了 4 个 SHA- 3 哈希算法,SHA3-224、SHA3-256、SHA3-384 和 S HA3-512
|
||||
- ......
|
||||
|
||||
@ -121,17 +263,17 @@ _Guide 哥:说白点就是多了层封装,JDK 开发组的人没少看市面
|
||||
//判断字符串是否为空
|
||||
" ".isBlank();//true
|
||||
//去除字符串首尾空格
|
||||
" Java ".strip();// "Java"
|
||||
" Java ".strip();// "Java"
|
||||
//去除字符串首部空格
|
||||
" Java ".stripLeading(); // "Java "
|
||||
" Java ".stripLeading(); // "Java "
|
||||
//去除字符串尾部空格
|
||||
" Java ".stripTrailing(); // " Java"
|
||||
" Java ".stripTrailing(); // " Java"
|
||||
//重复字符串多少次
|
||||
"Java".repeat(3); // "JavaJavaJava"
|
||||
"Java".repeat(3); // "JavaJavaJava"
|
||||
|
||||
//返回由行终止符分隔的字符串集合。
|
||||
"A\nB\nC".lines().count(); // 3
|
||||
"A\nB\nC".lines().collect(Collectors.toList());
|
||||
"A\nB\nC".lines().count(); // 3
|
||||
"A\nB\nC".lines().collect(Collectors.toList());
|
||||
```
|
||||
|
||||
### ZGC:可伸缩低延迟垃圾收集器
|
||||
@ -158,31 +300,20 @@ Java 11 对 Java 9 中引入并在 Java 10 中进行了更新的 Http Client API
|
||||
使用起来也很简单,如下:
|
||||
|
||||
```java
|
||||
var request = HttpRequest.newBuilder()
|
||||
|
||||
.uri(URI.create("https://javastack.cn"))
|
||||
|
||||
.GET()
|
||||
|
||||
.build();
|
||||
|
||||
var client = HttpClient.newHttpClient();
|
||||
|
||||
// 同步
|
||||
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
System.out.println(response.body());
|
||||
|
||||
// 异步
|
||||
|
||||
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
|
||||
|
||||
.thenApply(HttpResponse::body)
|
||||
|
||||
.thenAccept(System.out::println);
|
||||
var request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://javastack.cn"))
|
||||
.GET()
|
||||
.build();
|
||||
var client = HttpClient.newHttpClient();
|
||||
|
||||
// 同步
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
System.out.println(response.body());
|
||||
|
||||
// 异步
|
||||
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenAccept(System.out::println);
|
||||
```
|
||||
|
||||
### 简化启动单个源代码文件的方法
|
||||
|
Loading…
x
Reference in New Issue
Block a user