117 lines
4.8 KiB
Markdown
117 lines
4.8 KiB
Markdown
---
|
||
title: Java 10的新特性
|
||
tags:
|
||
- JVM
|
||
- Java
|
||
- Java 10
|
||
- 新特性
|
||
- 局部变量
|
||
- 类型推断
|
||
- G1
|
||
- 不可变集合
|
||
categories:
|
||
- - JVM
|
||
- Java
|
||
keywords: 'Java,Java 10,新特性,局部,变量,推断,G1,不可变,集合'
|
||
date: 2021-05-20 17:11:56
|
||
---
|
||
|
||
自从Java 9发布时候,时隔半年,Java 10就问世了。这都归功于Oracle对于Java版本发布策略的变化。相比Java 9,Java 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`,最小可使用的系统内存比例。
|
||
|