概述
JDK 10 于 2018 年 3 月 20 日正式发布。
变动说明
官网:
更多参考:
重要变更和信息
JDK 10 包含 12 个 新特性 ,其中比较重要的有:
- JEP 286: Local-Variable Type Inference 局部变量的类型推导
- JEP 296: Consolidate the JDK Forest into a Single Repository 将JDK 的多个代码仓库合并到一个代码仓库中
- JEP 304: Garbage-Collector Interface
- JEP 307: Parallel Full GC for G1
- JEP 310: Application Class-Data Sharing 应用程序类数据共享
- JEP 312: Thread-Local Handshakes 线程-局部变量管控
- JEP 313: Remove the Native-Header Generation Tool (javah) 移除Native-Header生成工具javah
- JEP 314: Additional Unicode Language-Tag Extensions 额外的 Unicode 语言标签扩展
- JEP 316: Heap Allocation on Alternative Memory Devices 备用存储装置上的堆分配
- JEP 317: Experimental Java-Based JIT Compiler 基于 Java 的 实验性 JIT 编译器
- JEP 319: Root Certificates 根证书
- JEP 322: Time-Based Release Versioning 基于时间的版本发布模式
而其中与开发过程中直接相关的特性包括:JEP 286(局部变量的类型推导)等。
下载地址
您可以从这个链接下载生产就绪的OpenJDK版本。文件为压缩包,解压并设置环境变量就可以使用。
当然你也可以从这个链接下载Oracle JDK版本(但是需要注意商用限制),更多版本下载。
Java10新特性总结
1、JEP 286:局部变量的类型推导
目前为止,局部变量类型推导是 Java 10 中最受人瞩目的特性。在经过激烈的争议之后,此特性才被引入 Java 10 中,它允许编译器推导局部变量的类型,而不是要求程序员明确指定变量类型。局部变量类型推导有助于缩短代码,并提高可读性。
简单类型
以String类型为例,示例代码:
// 无类型推导
String name = "四书五经";
// 使用类型推导
var name = "四书五经";
可以看到,唯一的区别在于使用了保留类型名称 var 。使用右侧的表达式,编译器可以推导出变量 name 的类型为 String 。
复杂类型
以List为例,示例代码:
// 无类型推导
List<String> list = new ArrayList<>();
// 使用类型推导,注意右侧泛型也可以不加,不加就相当于泛型为Object
var list = new ArrayList<String>();
编译器可以推导出变量 list 的类型为 ArrayList 。
在早期Java引入泛型的时候,我们申明具体类型的时候需要这样写(等号两边都需要):
List<String> list = new ArrayList<String>();
Map<String, String> map = new HashMap<String,String>();
后来在Java 7推出之后,简化为(只需要在左边申明类型即可):
List<String> list = new ArrayList<>();
Map<String, String> map = new HashMap<>();
而这次Java 10中,对类型的推导进一步优化,只需要这样即可(类型在等号右边决定):
var list = new ArrayList<String>();
var map = new HashMap<String, String>();
对于var的使用还有几点要注意的:
- 定义的时候必须初始化
- 只能用于定义局部变量
- 不能用于定义成员变量、方法参数、返回类型
- 每次只能定义一个变量,不能复合声明变量
- 大量使用var可能会导致代码的可读性下降,因此尽量在情况明显的情况下才使用它。
顾名思义,局部变量类型推导特性只能用于局部变量。不能将它用于定义实例或类变量,也不能在方法参数或返回类型中使用它。但是,在可以从迭代器推导类型的经典和增强的 for 循环中, 可以 使用 var 。
for(var user : users){
}
for(var i = 0; i < 10; i++){
}
var的问题
1. var 让类型变得模糊
前面已经提到var 有一些好处,但是另一方面,它也有可能让类型变得模糊。
var result = userService.search();
上面的代码中,我们必须猜测返回类型。让代码更加难以维护。
2. var 无法与 lambda 结合使用
在用于 lambda 表达式时,类型推导的效果不是很好,主要由于缺乏可供编译器使用的类型信息。清单 8 中的 lambda 表达式不会执行编译。
示例代码:
Function<String, String> msgWarpper = m -> "'" + m + "'";
var msgWarpper1 = m -> "'" + m + "'"; //这行编译会报错,需要使用上一行的形式
在上述代码中,右侧表达式中没有足够的类型信息供编译器推导变量类型。Lambda 语句必须始终声明一个显式类型。
Java官方表示,它不能用于以下几个地方:
- 方法参数
- 构造函数参数
- 方法返回类型
- 字段
- 捕获表达式(或任何其他类型的变量声明)
2、JEP 296:将JDK 的多个代码仓库合并到一个代码仓库中
3、JEP 304+JEP 307:GC改进和内存管理
JDK 10中有2个JEP专门用于改进当前的垃圾回收。
统一的垃圾回收接口(JEP 304)
- 它将引入一个纯净的垃圾收集器接口
- 以帮助改进不同垃圾收集器的源代码隔离。
- 其重点在于通过完全GC 并行来改善G1最坏情况的等待时间。
- G1是Java 9中的默认GC,并且此JEP的目标是使G1平行。
4、JEP 310:应用程序类数据共享
Java 10中引入了应用程序类数据共享(Application Class Data Sharing,AppCDS)功能,它可以将应用程序类的共享部分缓存到本地内存中,从而提高启动速度和内存使用效率。
5、JEP 312:线程-局部变量管控
JDK 10引入一种 在线程上执行回调的新方法,因此这将会很方便能停止单个线程,而不是停止全部线程或者一个都不停。
6、JEP 313:移除Native-Header生成工具javah
javah 工具曾用于生成 C 头文件(扩展名为 .h),这些文件对于 Java 代码中声明的 native 方法是必需的,它主要用于实现 Java 与本地代码(如 C 或 C++)之间的交互。
然而,在 Java 9 中,该工具被标记为过时,在 Java 10 中正式移除,这是因为从 Java 8 版本开始,javac 编译器新增了 -h 选项,可以在编译 Java 源代码的过程中直接生成相应的 native 方法头文件。随着 javac 功能的增强,javah 的存在变得多余,其移除有助于简化整个工具链。
7、JEP 314:额外的 Unicode 语言标签扩展
目标是增强java.util.Locale及其相关的API,以便实现语言标记语法的其他Unicode扩展(BCP 47)。
8、JEP 316:备用存储装置上的堆分配
允许HotSpot VM 在备用内存设备上分配Java对象堆内存,该内存设备将由用户指定。
9、JEP 317:基于 Java 的 实验性 JIT 编译器
Oracle希望将其Java JIT编译器Graal用作Linux / x64平台上的实验性JIT编译器。
10、JEP 319:根证书
在JDK中提供一组默认的根证书颁发机构(CA)证书。
尽管自 Java 9 起,keytool 工具新增了 -cacerts 参数以供查看当前 JDK 管理的根证书,但 Java 9 中的 cacerts 文件是空的,这意味着开发者需要手动安装和管理根证书,这无疑增加了开发的复杂性。为了简化这一过程,从 Java 10 开始,JDK 将内置一组默认的 CA 根证书。这些开源的根证书由 OpenJDK 社区提供,使得开发者无需手动配置 CA 根证书,因为它们已经预装在 JDK 中了。
11、JEP 322:基于时间的版本发布模式
针对当前和未来基于时间的发布模型,修改Java SE平台和JDK的版本字符串方案以及相关的版本控制信息。
12、删除的工具
Java 10 删除了一些工具:
- 命令行工具
javah,但您可以使用javac -h代替它。 - 命令行选项
-X:prof,但您可以使用jmap工具来访问探查信息。 policytool。
一些由于 Java 1.2 被永久删除而被标记为弃用的 API。这些 API 包括 java.lang.SecurityManager.inCheck 字段和以下方法:
java.lang.SecurityManager.classDepth(java.lang.String)java.lang.SecurityManager.classLoaderDepth()java.lang.SecurityManager.currentClassLoader()java.lang.SecurityManager.currentLoadedClass()java.lang.SecurityManager.getInCheck()java.lang.SecurityManager.inClass(java.lang.String)java.lang.SecurityManager.inClassLoader()java.lang.Runtime.getLocalizedInputStream(java.io.InputStream)java.lang.Runtime.getLocalizedOutputStream(java.io.OutputStream)
13、弃用的API
JDK 10 也弃用了一些 API。 java.security.acl 包被标记为弃用, java.security 包中的各种相关类( Certificate 、 Identity 、 IdentityScope 、 Singer 、 auth.Policy )也是如此。此外, javax.management.remote.rmi.RMIConnectorServer 类中的 CREDENTIAL_TYPES 也被标记为弃用。 java.io.FileInputStream 和 java.io.FileOutputStream 中的 finalize() 方法已被标记为弃用。 java.util.zip.Deflater / Inflater / ZipFile 类中的 finalize() 方法也是如此。