资讯专栏INFORMATION COLUMN

JDK 10 的新特性和增强功能

yibinnn / 2259人阅读

摘要:的问题在于,版本号中编码了它和它对之前版本的兼容性信息。但是在六个月节奏的情况下,这些信息都是未知的,在发布前任何事情都可能发生,由此规范下的版本号也会是未知的。程序会对文件的完整性做一个保护,因此修改既可能丢失。

本文是对底部参考资料的整理得到的,由于本人技术水平和英语水平都不是很高,有些词如有翻译错误或句子的理解错误还请指出。
JEP 286 局部变量推断: var

传统的 Java 代码中,声明一个变量是非常繁琐的:

List list = new ArrayList();

现在则引入了 var,既保持 Java 对静态类型安全的承诺,又能让开发者省略不必要的局部变量类型的声明。

比如像这样:

var list = new ArrayList();

var 只能用在以下情况:

声明的同时赋值,比如上面那个例子

增强的 for 循环中的索引 (这将在后面提到)

传统 for 循环中声明的本地变量

它不能被用于方法签名、构造器声明、方法返回类型、字段、异常捕获或任何其他类型的变量声明。

类型推断在 Java 8 中已经得到了显著的扩展,包括了对嵌套和链接的泛型方法的推导以及 lambda 表达式的推导,比如下面这样:

int maxWeight = blocks.stream()
                    .filter(b -> b.getColor() == BLUE)
                    .mapToInt(Block::getWeight)
                    .max();

没有必要去在意 blocks.stream*() 返回的是 Stream,也不用在意 filterlambda 表达式的参数类型没有被显式声明,因为它们都能通过类型推导得到。

对于局部类型变量,类型推导是非常有用的,因为通常情况下都可以写成下面这种代码:

var path = Paths.get(fileName);
var bytes = Files.readAllBytes(path);

但是要注意的是,var 并不是一个关键字,而是一个保留的类型名称,这意味着你可以将一个变量、方法、包名写成 var 。不过一般情况下不会有人这么写的,因为这本身就违反了普遍的命名规范。

var 不能用来声明没有赋值的变量、不能用于声明多个变量的情况、不能声明具有额外纬度的数组或引用了正在初始化的其他变量的变量。

JEP 322 基于时间的版本号管理

JEP 223 引入的版本号方案相比之前的方法都要好很多,但是对于现在 Java 所走的 六个月节奏 并不适合。

JEP 223 的问题在于,版本号中编码了它和它对之前版本的兼容性信息。但是在 六个月节奏 的情况下,这些信息都是未知的,在发布前任何事情都可能发生,由此 JEP 223 规范下的版本号也会是未知的。

JEP 223 的语义中,每个基于 JDK 构建或使用组件的开发者(包括 JDK 的发布者)都必须提前敲定版本号,然后切换过去。而库、框架和工具的开发者则必须在代码中修改检查版本号的相关代码,这造成了混乱。

更多关于 JEP 322 的详细情况请访问这里。

core-libs/java.util Optional.orElseThrow() 方法

此次更新中为 Optional 类添加了一个新的方法,这个方法与 orElseThrow(exSupplier) 是不同的,它没有参数。

Optional.get() 是一个容易误导程序员的方法,它实际上有可能抛出 NoSuchElementException 运行时异常,因此需要一个语义明确的方法来帮助程序员清楚的认识到自己在做什么。

在之前的规划中,Optional.getWhenPresent() 是一个备选方法,虽然这个名字强调了值一定会存在,但是其中的 when 似乎会让人觉得这是个阻塞方法。因此最后委员会选择了 Optional.orElseThrow(),但是 Optional.get() 并没有被单纯得弃用。

Unicode 标签扩展

增强了 java.util.Locale 和相关 API 以实现关于 BCP 47 语言标签Unicode 扩展。

详情请访问这里

core-libs/java.util 创建不可变集合的一系列 API

新的 API 中包括了一些用于创建不可见集合的方法:

List.copyOfSet.copyOfMap.copyOf() 可以用来从已有的集合中创建一个新的集合;

toUnmodifiableListtoUnmodifiableSettoUnmodifiableMap 则存在于 Stream.Collectors 类中,通过它们可以将流的元素收集到一个不可变集合当中。

copyOf 系列的方法签名基本是下面这样:

static  List  copyOf (Collection  coll)

SetMap 也会有类似的方法。

值得注意的是,这个方法会检测 coll 是不是一个 不可变 的集合,如果是,则会直接返回该引用,相当于一个浅拷贝。

另外对于不可变集合而言,下面这种情况是被允许的:

List  list = List.of(...);
List  newList = List.copyOf(list);

这对于可变集合而言是不允许的,因为这可能会导致堆污染。

core-svc/java.lang.management 用于关闭 JRE Last Usage Tracking 的系统属性

引入了新的 jdk.disableLastUsageTracking 属性以禁用 JVMJRE 上次使用情况追踪 功能。

如果使用了此属性,那么 com.oracle.usagetracker.track.last.usage 的设置将被忽略。

core-svc/java.lang.management 开箱即用的 JMX 代理使用的散列密码

在以前,JMX 存储的是明文密码,当时 (2014 年) 大家已经开始手动生成散列密码来替换明文密码,因为这可以避免一些攻击,同时盐 (salt) 的存在可以让散列密码的强度更上一层。但是对于管理员而言,即使是使用诸如 Python 之类的脚本语言来生成散列密码,这仍然是极容易出错的。因此最好的办法是用户只需要提供明文密码,让 JMX 来处理散列之类的事情。

JMX 现在会使用密码的 SHA3-512 散列结果来覆盖存储在 jmxremote.password 中的明文密码。

其格式如下:

role_name W hashedPassword

其中:

role_name 是任何不含空格或制表符的字符串

W 是一个空格或制表符

散列密码的格式如下:

hashedPassword = base64_encoded_64_byte_salt W base64_encoded_hash W hash_algorithm

其中:

base64_encoded_64_byte_salt 是 64字节的随机值

base64_encoded_hashHash_algorithm(password + salt) 的结果

W 是一个空格或制表符

hash_algorithm 是列表 中指定的算法名称。这是个可选项,默认值为 SHA3-512

如果密码是明文的,且满足以下条件,那么将被散列值覆盖

management.properties 文件中 com.sun.management.jmxremote.password.toHashes 属性被设为 true

密码文件是可写的

安全管理器处于打开状态的情况下系统安全策略允许对密码文件进行写入

如果想更改角色的密码,可以将旧的散列密码替换为新的明文密码或新的散列密码。如果新的密码是明文的,那么在新的登录发生时系统会使用其散列值替换明文密码。

文件中的角色应该至少有一条记录,否则该角色将无权访问;如果同一个用户下有多条记录,那么会使用最后一条记录。

用户可以自行根据上述的格式来生成的散列值,以替换旧的密码。

文件被拥有者以外的用户访问时将导致错误并退出程序。

为了防止在生产环境中对密码文件进行了无意的编辑,建议只部署可读的散列密码文件。明文密码的散列密码列表可以用 JMX 代理预先生成。

JMX 运行期间,建议不要编辑密码文件。程序会对文件的完整性做一个保护,因此修改既可能丢失。

hotspot/gc JEP 307 G1 的 完全并行 GC

G1 垃圾收集器就是为了避免 完全 GC (full collections) , 但是当并行收集无法快速回收内存时,会产生一次 完全回退 GC (fall back full GC) 。

之前 G1完全GC 使用的是单线程标记扫描压缩算法(mark-sweep-compact),现在通过 JEP 307完全GC 得以并行化,同时现在会使用与 年轻代混合收集 相同的并行工作线程数量。

security-libs/java.security JEP 319 根证书

OpenJDK 中的 cacerts 密钥库在相当长一段时间内是空的,这将导致未指定 javax.net.ssl.trustStore 属性的情况下 TLS 连接 的创建会被阻止。现在OracleJava SE 根证书 被填充至 OpenJDKcacerts 中。

security-libs/javax.net.ssl TLS 会话散列主密钥扩展 的支持

在是一个对 RFC 7627 的支持。

如果出现兼容问题,可以将 jdk.tls.useExtendedMasterSecret 设置为 false 来禁用此扩展的协商。

如果 jdk.tls.allowLegacyResumption 值为 false,当会话散列和主密钥扩展未协商的情况下,程序可以拒绝简短握手。

如果 jdk.tls.allowLegacyMasterSecret 值为 false,应用将拒绝不支持此扩展的连接。

tools/javac 增强 for 循环的字节码生成

之前的 for 循环在遍历一个大的列表/数组时,它会隐式得持有一个临时引用,而且这个临时引用不会被释放以至于可能产生 OutOfMemoryError 异常,详细的情况可以查看这里。

对于下面的 Java 代码:

List data = new ArrayList<>();
for (String b : data);

将会被编译为:

{
    /*synthetic*/
    Iterator i$ = data.iterator();
    for (; i$.hasNext(); ) {
        String b = (String) i$.next();
    }
    b = null;
    i$ = null;
}

这意味着 GC 可以发现不再被使用的 i$ 所占用的内存并回收它,这对于数组也是适用的。

tools/javadoc(tool) javadoc 支持多个样式表

新的 javadoc 命令行选项 --add-stylesheet ,它支持在生产的文档中使用多个样式表。

而现有的选项 -stylesheetfile 有了一个别名 stylesheetfile --main-stylesheet,用以区分主样式表和其他样式表,更多信息可以查看 javadoc 文档。

tools/javadoc(tool) 覆写没有改变规范的方法

默认情况下,如果有方法覆写了超类中的方法,那么 javadoc 会为它生成文档。

但是如果一个方法只是被覆写但是没有改变语义行为时,javadoc 只会在原方法摘要中用 @inheritdoc 标记它。

现在新的选项 --overridden-methods=value 可以将许多 不改变规范的覆写方法 与其他继承而来的方法分组,而不是在类的声明中与其他方法一起被记录在文档中。

tools/javadoc(tool) API 描述中摘要的注释标记

{@summary ...} 是一个新的行内标记。默认情况下,会通过简单算法或 java.text.BreakIterator 对描述中的第一句话进行判断以确定 API 描述内容的摘要,但是这种方法可能会对第一句话结尾有错误的判断,因此新的标签可以显式得指定 API 的描述摘要。

参考资料

JDK 10 Release Notes

Java SE 10 (18.3) ( JSR 383) Final Release Specification

JEP 286 Local-Variable Type Inference

JEP 322: Time-Based Release Versioning

JEP 314: Additional Unicode Language-Tag Extensions

JDK-8140281 : (opt) add no-arg orElseThrow() as preferred alternative to get()

JDK-8177290 : add copy factory methods for unmodifiable List, Set, Map

JDK-5016517 : Replace plaintext passwords by hashed passwords for out-of-the-box JMX Agent

JDK-8172890 : JEP 307: Parallel Full GC for G1

JDK-8189131 : Open-source the Oracle JDK Root Certificates

JDK-8148421 : Transport Layer Security (TLS) Session Hash and Extended Master Secret Extension

JDK-8175883 : bytecode generated for the enhanced for loop may block memory garbage collecting

JDK-8185371 : Support for multiple stylesheets in javadoc

JDK-8157000 : Do not generate javadoc for overridden method with no spec change

JDK-8173425 : Javadoc needs a new tag to specify the summary.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76337.html

相关文章

  • 聊聊 Java8 以后各个版本的新特性

    摘要:于是抽时间看了看以后各个版本的特性,做了一个总结。年和公开版本发布,取名为。此后对应版本就是,。发布,是一个重大版本更新。在此之后,就是每六个月发布一次新版本。以上和参考资料聊了一些关于的历史,下面我们看看各个版本有那些新特性。 【这是 ZY 第 11 篇原创技术文章】 某天在网上闲逛,突然看到有篇介绍 Java 11 新特性的文章,顿时心里一惊,毕竟我对于 Java 的版本认识...

    K_B_Z 评论0 收藏0
  • Java 1010个新特性,将彻底改变你写代码的方式!

    摘要:的新特性说了这么多,看都会有哪些特性来改变我们写代码的方式呢局部变量类型推断局部变量类型推断可以说是中最值得注意的特性,这是语言开发人员为了简化应用程序的编写而采取的又一步,如下图所示。 showImg(https://segmentfault.com/img/remote/1460000015356980); Java 9才发布几个月,很多玩意都没整明白,现在Java 10又快要来了...

    ityouknow 评论0 收藏0
  • Java12的新特性

    摘要:的这个特性新增了两个参数分别是及,设置为的话,表示禁用。语法层面引入了版本的层面引入了,引入,让支持,对等新增方法方面引入了版本的,不过的没有另外主要对及进行了改进其中对支持了,默认是开启,使用可以禁用对于则新增支持以及特性 Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新...

    liujs 评论0 收藏0
  • Netbeans 8发布 支持Java 8

    摘要:和同步发布的是的。和支持,包括现成的和配置及数据源。更加灵活的提示,可以禁用和启用该提示并更改警告级别。导航器显示目标。新的测试运行器支持。新的修复程序支持。版本控制增强功能支持工作副本,各种和支持增强功能。 和Java8同步发布的是Oracle的NetBeansIDE 8。NetBeans IDE 8.0 提供了现成的代码分析器和编辑器,可在其中使用最新的 Java 8 技术 -- ...

    沈俭 评论0 收藏0
  • JDK 5 ~ 10特性倾情整理!

    摘要:最近连都在准备发布的路上了,大家都整明白了吗也许现在大部分人还在用,的新特性都没用熟,刚出不久,就不用说了。 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了。 为了大家对JDK有一个全面的了解,下面我为大家整理了JDK5~10的所有关键新特性! JDK5新特性 自动装箱与拆箱 枚举 静态导...

    godiscoder 评论0 收藏0

发表评论

0条评论

yibinnn

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<