blog/source/_posts/nf-java10.md
2021-05-20 17:12:42 +08:00

117 lines
4.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Java 10的新特性
tags:
- JVM
- Java
- Java 10
- 新特性
- 局部变量
- 类型推断
- G1
- 不可变集合
categories:
- - JVM
- Java
keywords: ''
date: 2021-05-20 17:11:56
---
自从Java 9发布时候时隔半年Java 10就问世了。这都归功于Oracle对于Java版本发布策略的变化。相比Java 9Java 10没有引入特别多的变化这也是因为各个版本间的发布周期变短使新引入功能的稳定时间变短导致的。<!-- more -->
本系列的文章有:
- {% post_link nf-java8 %}
- {% post_link nf-java9 %}
- {% post_link nf-java10 %}
- {% post_link nf-java11 %}
- {% post_link nf-java12 %}
- {% post_link nf-java13 %}
- {% post_link nf-java14 %}
- {% post_link nf-java15 %}
- {% post_link nf-java16 %}
## 局部变量类型推断
局部变量类型推断是Java 10中引入的最值得注意的特性。这个特性实际上就是一个语法糖可以简化并改善开发者的书写体验。
我们最常诟病Java的地方就是它的繁琐和冗长。局部类型推断的引入直接减少了最常使用的变量定义部分的代码长度。例如下面这个示例。
```java
// 在Java 10之前
Map<String, Integer> map = new HashMap<>();
// 在Java 10以后
var map = new HashMap<String, Integer>();
```
从上面这个示例可以看出来,新引入的`var`关键字承担起了定义变量时声明变量类型的功能。`var`关键字指示编译器按照赋值表达式右值的类型来定义左值的类型换句话说就是随意定义变量而不必指定变量的具体类型。满满的JavaScript即视感。
可能对于上面这个示例对于代码量的缩减并没有那么直观的感受,那么以下再引申一个示例出来。
```java
var entries = map.entrySet();
```
好了,现在再来对比看一下变量`entries`的类型。
虽然`var`关键字引入了许多方便,但是这个关键字的使用是受到限制的,一般推荐在以下场景中使用:
- 局部变量初始化。
- `for`循环的内部索引变量。
- 传统`for`循环声明的变量。
其实从这几个场景可以看出来,关键字`var`所能够应用到的场景,都是类型已经完全确定的位置。所以在以下几个场景里,`var`就不能够使用了。
- 构造函数和方法的参数。
- 方法的返回类型。
- 类中属性定义。
- `catch`表达式。
在这些位置中,变量的类型都是无法确定的,必须要显式声明的。
!!! caution ""
需要注意的是,如果在代码中大量的使用`var`关键字,是比较容易导致代码的可读性变差的。
## 不可变集合
`java.util.List`、`java.util.Map`和`java.util.Set`这三个接口都增加了一个静态方法`.copyOf()`,可以用来形成不可变集合对象。
```java
var copyList = List.copyOf(originIntList);
```
这样复制出来的`copyList`是不能做任何修改操作的,如果对其进行了修改,就会抛出`UnsupportedOperationException`。
另一个可以用来形成不可变集合的方法是`java.util.stream.Collectors.toUnmodifiable()`。
```java
var evenList = originIntList.stream()
.filter(i -> i % 2 == 0)
.collection(Collectors.toUnmodifiableList());
```
这个方法可以将一个Stream收集起来变为一个不可变集合。如果要对其形成的集合进行修改也同样会抛出`UnsupportedOperationException`。
## Optional
Optional系列类增加了一个方法`.orElseThrow()`,用来快速抛出`NoSuchElementException`。在Java 10之前要在Optional中抛出异常必须显式指定异常的类型。现在新添加的`.orElseThrow()`只是一个常用操作的简化形式。
## 开源根证书
Oracle在Java 10中开源了根证书这使得OpenJDK和OracleJDK之前的差距缩小了。这也使得原本在OpenJDK中需要经过大量配置才能够正常工作的诸如TLS等安全功能变得可以比较便捷地使用。
## 改进GC
G1垃圾收集器是在Java 9中引入的默认GC在Java 10中通过优化Full GC改善了G1的最坏等待时间增强了GC的性能。
## 加入容器化支持
Java 10的JVM可以通过配置感知到自身所处的环境是否是虚拟环境这对JVM获取系统环境信息的操作有影响。要启用JVM的容器化支持只能在Linux平台中使用。
新加入的JVM选项`-XX:-UseContainerSupport`可以用来指示JVM启用容器化支持。随着容器化支持一并加入的JVM选项还有以下这些用于精细调整JVM所使用系统资源的选项。
- `-XX:ActiveProcessorCount=n`指示JVM可以使用的CPU数量。
- `-XX:InitialRAMPercentage`初始可以用作Java堆内存的系统内存比例。
- `-XX:MaxRAMPercentage`,最大可使用的系统内存比例。
- `-XX:MinRAMPercentage`,最小可使用的系统内存比例。