Java10的主要新特性总结

135 阅读8分钟

概述

JDK 10 于 2018 年 3 月 20 日正式发布。

变动说明

官网:

docs.oracle.com/javase/10/l…

www.oracle.com/java/techno…

openjdk.org/projects/jd…

更多参考:

docs.oracle.com/javase/10/

docs.oracle.com/javase/10/m…

重要变更和信息

JDK 10 包含 12 个 新特性 ,其中比较重要的有:

而其中与开发过程中直接相关的特性包括:JEP 286(局部变量的类型推导)等。

下载地址

您可以从这个链接下载生产就绪的OpenJDK版本。文件为压缩包,解压并设置环境变量就可以使用。

当然你也可以从这个链接下载Oracle JDK版本(但是需要注意商用限制),更多版本下载

Java10新特性总结

1、JEP 286:局部变量的类型推导

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的使用还有几点要注意的:

  1. 定义的时候必须初始化
  2. 只能用于定义局部变量
  3. 不能用于定义成员变量、方法参数、返回类型
  4. 每次只能定义一个变量,不能复合声明变量
  5. 大量使用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 的多个代码仓库合并到一个代码仓库中

JEP 296

3、JEP 304+JEP 307:GC改进和内存管理

JDK 10中有2个JEP专门用于改进当前的垃圾回收。

统一的垃圾回收接口(JEP 304

  • 它将引入一个纯净的垃圾收集器接口
  • 以帮助改进不同垃圾收集器的源代码隔离。

并行全垃圾回收器 G1(

  • 其重点在于通过完全GC 并行来改善G1最坏情况的等待时间。
  • G1是Java 9中的默认GC,并且此JEP的目标是使G1平行。

4、JEP 310:应用程序类数据共享

JEP 310

Java 10中引入了应用程序类数据共享(Application Class Data Sharing,AppCDS)功能,它可以将应用程序类的共享部分缓存到本地内存中,从而提高启动速度和内存使用效率。

5、JEP 312:线程-局部变量管控

JEP 312

JDK 10引入一种 在线程上执行回调的新方法,因此这将会很方便能停止单个线程,而不是停止全部线程或者一个都不停。

6、JEP 313:移除Native-Header生成工具javah

JEP 313

javah 工具曾用于生成 C 头文件(扩展名为 .h),这些文件对于 Java 代码中声明的 native 方法是必需的,它主要用于实现 Java 与本地代码(如 C 或 C++)之间的交互。

然而,在 Java 9 中,该工具被标记为过时,在 Java 10 中正式移除,这是因为从 Java 8 版本开始,javac 编译器新增了 -h 选项,可以在编译 Java 源代码的过程中直接生成相应的 native 方法头文件。随着 javac 功能的增强,javah 的存在变得多余,其移除有助于简化整个工具链。

7、JEP 314:额外的 Unicode 语言标签扩展

JEP 314

目标是增强java.util.Locale及其相关的API,以便实现语言标记语法的其他Unicode扩展(BCP 47)。

8、JEP 316:备用存储装置上的堆分配

JEP 316

允许HotSpot VM 在备用内存设备上分配Java对象堆内存,该内存设备将由用户指定。

9、JEP 317:基于 Java 的 实验性 JIT 编译器

JEP 317

Oracle希望将其Java JIT编译器Graal用作Linux / x64平台上的实验性JIT编译器。

10、JEP 319:根证书

JEP 319

在JDK中提供一组默认的根证书颁发机构(CA)证书。

尽管自 Java 9 起,keytool 工具新增了 -cacerts 参数以供查看当前 JDK 管理的根证书,但 Java 9 中的 cacerts 文件是空的,这意味着开发者需要手动安装和管理根证书,这无疑增加了开发的复杂性。为了简化这一过程,从 Java 10 开始,JDK 将内置一组默认的 CA 根证书。这些开源的根证书由 OpenJDK 社区提供,使得开发者无需手动配置 CA 根证书,因为它们已经预装在 JDK 中了。

11、JEP 322:基于时间的版本发布模式

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 包中的各种相关类( CertificateIdentityIdentityScopeSingerauth.Policy )也是如此。此外, javax.management.remote.rmi.RMIConnectorServer 类中的 CREDENTIAL_TYPES 也被标记为弃用。 java.io.FileInputStreamjava.io.FileOutputStream 中的 finalize() 方法已被标记为弃用。 java.util.zip.Deflater / Inflater / ZipFile 类中的 finalize() 方法也是如此。