Java17新特性
Java 17 将是 Java 的下一个 LTS 版本。长期支持 (LTS) 它是一种产品生命周期管理策略,其中计算机软件的稳定版比标准版维护时间长。这个术语通常保留在开源软件上,描述了支持软件版本数月或数年的软件版本。
JEP 415:特定于上下文的反序列化过滤器
允许使用应用程序 JVM 范围内的过滤器工厂配备了具有上下文和动态选择的反序列化过滤器,用于选择每个反序列化操作的过滤器。
动机:
-
不可信数据的反序列化是一个具有内部风险的操作,因为在许多情况下,通过未知或未经身份验证的客户端获得传入数据流的内容。
-
防止序列化攻击的关键是禁止任何类别的例子被反序列化,以直接或间接地阻止其方法的执行。
-
攻击者可以通过仔细构建流程来操作任何恶意类中的代码。如果对象结构涉及改变状态或触发其他操作的副作用,则应用程序对象、库对象和 Java 运行时的完整性可能会受到损害。
JEP 414:Vector API (第二个孵化器)
引入与平台无关的矢量 API,它首先集成到 JDK 16 中,并将在 JDK 17 再次孵化,表达矢量计算,在运行过程中可靠编译 CPU 性能优于等效标量计算的最佳矢量指令。
JDK 17 中的向量 API 改进了性能和实现,包括字节向量和布尔数组之间转换的增强功能。
目标:
-
清晰简洁的 API: API 各种向量计算应能以清晰简洁的方式表达。
-
平台不可知: API 应该独立于 CPU 允许在支持向量指令的各种架构上实现架构。
-
在 x64 和 AArch64 编译和性能可靠的操作时间
-
优雅降级:如果向量计算不能有效地编译成向量指令,则会发出警告。
JEP 412:外部函数和内存 API (孵化器)
引入一个 API,外部函数的有效调用(即 JVM 外部代码)和安全访问外部内存(即不由自主 JVM 允许处理内存) Java 程序调用调用本地库和处理本地数据 JNI 的风险.
在这个 JEP 提案中有两个早期孵化 API 演变:外部内存访问 API 与外部链接器 API。以前在 Java 14、15 和 Java 16 中针对的
目标:
-
易用性:用 Java 本机接口 (JNI) 替换卓越的纯 Java 开发模型。
-
性能:与现有 API(如 JNI 或 sun.misc.Unsafe)性能相似,如果不是更好。
-
常规:提供在各种类型的外部内存(如本机内存、持久内存和堆积内存)上工作的方法,并随时间适应其他平台(例如,x86 32 位)和用 C 外部函数(例如,C 、FORTAN)。
-
安全:默认不安全操作只有在应用程序开发人员或最终用户明确选择加入时才停止。
JEP 411:废除安全管理器
从 Java 1.0 一开始,有一个安全管理器。然而,它很少被使用多年。为了促进它 Java 安全管理器向前发展 Java 17 中被弃用,并将在未来版本中与旧 Applet API (JEP 398) 一起删除。
目标:
-
在开发人员 Java 准备在未来版本中删除安全管理器。
-
如果用户的 Java 依赖安全管理器的程序发出警报。
-
评估是否需要新的 API 或机制修复使用安全管理器的独特有限用例,如堵塞 System::exit。
JEP 410:删除实验性 AOT 和 JIT 编译器
删除实验基础 Java 的提前 (AOT) 和即时 (JIT) 由于使用有限,维护编译器所需的工作量非常重要。
即使保留了实验性 Java 级 JVM 编译器接口 (JVMCI),这样,开发人员也可以继续使用外部构建的编译版本和使用 Graal 编译器 ( GraalVM )进行 JIT 编译。
动机:
作为实验性功能,JDK 9 已提前编译(jaotc 集成工具 AOT 编译,jaotc 使用 Java 编写的 Graal 编译器。由于这些实验特性尚未使用,需要付出相当大的努力来维护和改进。Oracle 发布的 JDK 16 没有这样的功能,也没有人抱怨。
JEP 409:密封类
提出并作为密封类
密封和接口增强 Java 编程语言。密封和界面限制其他类别或界面的扩展或实现。
目标:
-
使类或接口作者能够控制要实现的代码。
-
限制超类使用的方法比访问修饰符更具声明性。
-
支持未来模式匹配方向,基于对趋势的彻底检查。
细化:
-
在 JLS 它描述了上下文关键字的定义,取代了之前对有限标识符和有限关键字的定义。
-
引入密封、非密封的字符序列,并允许它们作为上下文的关键字。
-
与匿名类和 lambda 表达式一样,在决定密封类或密封接口的隐式声明的允许子类时,局部类可能不是密封类子类。
一类可以使用 Sealed 密封装饰符 -允许它的声明。在任何地方extends 和 implements 子句之后,permit子句指定允许/允许扩展密封类。
示例:以下示例显示 Animal 如何指定三个允许的子类:
package com.techgeeknext.example.species;public sealed class Animalpermits Dog, Monkey, Leopard {...}
注意: permit 指定类必须靠近超级类,或在同一模块中,或在同一包中。
package com.techgeeknext.example.species;public sealed class Animalcom.techgeeknext.example.species.canis.Dog,com.techgeeknext.example.species.macaca.Monkey,com.techgeeknext.example.species.rana.Leopard{...}
JEP 407:删除 RMI 激活
调用删除远程方法 (RMI) 但应保留激活机制 RMI 其余部分。RMI 激活机制变得多余,不再使用。Java SE 15 中的 JEP 385 弃用,建议删除。
switch 模型匹配扩展 Java 允许验证各种模式的模式语言 switch 每种模式都有不同的模式都有不同的操作。这使得以简单和安全的方式表达复杂的数据查询成为可能。
JDK 16 中的 instanceof 运算符已扩展到接受模式和执行模式匹配。提案的适度扩展简化了众所周知的 instanceof-and-cast 习语。
目标:
-
允许模式出现 case 添加到标签中 switch 短语和句子的表达和适用性。
-
如有必要,放松历史转折点的零敌意。
-
介绍两种新模式:
-
保护模式:使用任何布尔表达式来优化模式匹配逻辑。
-
括号模式:清除分析歧义。
-
确保所有现有的 switch 用相同的语义编译表达式和句子,并在不做任何修改的情况下执行。
JEP 403:强封装 JDK 内部
强烈封装了 JDK 除了关键部元素外,所有内部元素都是关键内部元素 API,如 sun.misc.Unsafe. Unsafe。不再可能像从 JDK 9 到 JDK 16 这样,个命令行选项来放松内部部件的严格包装。
JEP 398:弃用 Applet API 以进行删除
Applet API 事实上,这是无用的,因为一切都是无用的 Web 浏览器供应商已删除或披露计划放弃 Java 支持浏览器插件。 Applet API 在 Java 9 已被弃用,但以前没有删除。
JEP 391:macOS/AArch64 端口
将 JDK 移植到新架构 macOS/AArch64 期待未来的需求
动机:
-
Apple 决定在其 Macintosh 计算机上从 x64 迁移到 AArch64。对于 Linux,AArch64 版本的 Java 已经可用,Windows 目前正在进行端口开发。
-
由于程序二进制接口与处理器寄存器集合等低级协议的差异,Java 开发人员计划通过编译使用条件来重用这些端口些端口 AArch64 代码,这是 JDK 端口标准。
-
MacOS/AArch64 的更改有可能拆分当前的Linux/AArch64、Windows/AArch64 和 MacOS/x64 端口,尽管可以通过预集成测试来减轻这种可能性。
JEP 382:新的 macOS 渲染管线
需要使用新的 Apple Metal 框架为 macOS 提供新的 Java 2D 渲染管道。与今天一样,Java 2D 完全依赖于 OpenGL。虽然 Apple 在 macOS 10.14 中弃用了 OpenGL 渲染库,但 Metal 框架取代了 OpenGL 渲染库。
目标:
-
为基于 macOS Metal 框架的 Java 2D API 提供功能齐全的渲染管道。
-
在选择的实际应用程序和基准测试中,提供与 OpenGL 管道相当或更好的性能。
-
与 OpenGL 管线共存,直至停产。
JEP 356:增强型伪随机数生成器
引入了伪随机数生成器 (PRNG) 的新接口和实现,其中包括可跳转 PRNG 和一类新的可拆分 PRNG 算法 (LXM)。
推动该计划的重点是 Java 伪随机数生成领域的多个改进领域。RandomGenerator 是一个现代接口,将为所有当前和新的 PRNG 提供统一的 API,以及四个专门的 RandomGenerator 接口。
目标:
-
使在不同的应用程序中使用不同的 PRNG 算法变得更简单。
-
通过提供 PRNG 对象的流,您可以更好地支持基于流的编程。
-
从当前 PRNG 组中删除冗余代码。
-
尽可能维护 java.util.Random 类的动作。
JEP 306:恢复始终严格的浮点语义
与其同时拥有严格的浮点语义 (strictfp) 和显着不同的默认浮点语义,不如让浮点运算统一严格。这将使语言和虚拟机恢复到它们原来的浮点语义,就像在 Java SE 1.2 中引入严格和默认浮点模式之前一样。
目标:
-
继续提高 JDK 的安全性和可维护性,这是 Project Jigsaw 的主要目标之一。
-
鼓励开发人员从内部部件转向标准 API,以便他们和他们的用户可以轻松升级到未来的 Java 版本。
JDK16的新特性
instanceof 模式匹配,Java 14 和 Java 15 都作为预览功能引入了,这个新的特性现在转正了,Java 17 后就可以放心大胆地使用了。
以前这样用:
// 先判断类型
if (obj instanceof String) {
// 然后转换
String s = (String) obj;
// 然后才能使用
}
现在可以这样用:
if (obj instanceof String s) {
// 如果类型匹配 直接使用
}
可以直接在 if 条件判断类型的时候添加一个变量,就不需要再强转和声明新的变量了。是不是特别简洁?
Record 记录类也是 Java 14 和 Java 15 作为预览功能引入的,提供了一种更紧凑的语法来声明类,作为不可变数据的透明载体,可以大大减少类中的一些模板代码。我在介绍 Java 14 的时候就希望这个特性能转正,结果 15 的时候没有转,直到 Java 16,终于转了。
以前这样写:
public final class Writer {
private final String name;
private final int age;
public Writer(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
现在可以这样写:
public record Writer(String name, int age) { }
一行代码就搞定,可以来看一下反编译后的字节码:
public final class Writer extends java.lang.Record {
private final java.lang.String name;
private final int age;
public Writer(java.lang.String name, int age) { /* compiled code */ }
public java.lang.String toString() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public java.lang.String name() { /* compiled code */ }
public int age() { /* compiled code */ }
}
也就是说,Java 帮我们自动继承了 Record 类,并提高了一些模板代码,比如说构造方法、toString()
、hashCode()
等等。
----JVM 改进----
ZGC(Z Carbage Collectior)是 Java 中最新的一种垃圾收集器,随后我打算专门分享一篇文章来介绍它,比较陌生的小伙伴可以不用管。ZGC 的目标就是低延迟,保证最大停顿时间在几毫秒之间,不管堆有多大或者存活的对象有多少。
即使是在大型堆上,也可以在 GC 安全点内实现亚毫秒级的暂停,从而提高应用程序的效率和性能。
新方案以较小的块来分配元空间内存,从而减少类加载器的开销和碎片。通过将未使用的元数据内存以更快的速度返回给操作系统来提高弹性,从而进一步提高应用程序的性能并降低内存的利用率。
----新工具和类----
Unix-Domain 套接字通道一直是大多数 Unix 平台的功能,这个版本就可以在 Windows 10 和 Windows Server 2019 中实现这个功能了。
此版本为了给用户提供更自然的安装体验,可以将 Java 应用程序打包成不同的本地格式,比如说可以在 Windows 上安装的 msi 和 exe,macOS 上安装的 pkg 和 dmg,以及 Linux 上的 deb 和 rpm。
----安全性----
此提议会将包装器类(比如 java.lang.Integer
)修改为基于值的(类似于 java.util.Optional)类。
此提议的目的是为了提高 JDK 的安全性和可维护性,鼓励开发人员从使用内部 API 迁移到使用标准的外部 API,以便开发人员和用户都可以更轻松地升级。
----孵化器和预览功能----
JDK 中增加了一个新的模块 vector,该 API 将使开发者可以轻松地用 Java 编写可移植的高性能矢量算法。
该 API 提供了纯静态类型的、纯 Java 代码的形式对本地代码进行访问。
此 API 使 Java 程序可以安全有效地对各种外部存储器(例如本机存储器、PMEP、托管堆存储器等)进行操作。
该类可以限制指定的类或接口来继承或实现它。
----提高 OpenJDK 开发者的生产效率----
剩下这些提议对 Java 用户(使用 Java 编写代码或者应用程序的人员)不直接可见,只对 Java 开发者(进行 OpenJDK 开发的人员)可见。因此,对于作为普通用户的我们来说,简单了解下就行了。
看过 OpenJDK 的小伙伴应该知道,Java 的虚拟机和编译器是用 C 和 C++ 两种语言实现的。所以启用 C++ 14 的语言特性应该会提高开发者的生产效率,之前用的 C++ 98/03语言标准。
Git 目前已经成为代码版本管理领域的绝对统治者,Java 也是顺应潮流。
OpenJDK 的 GitHub 地址:https://github.com/openjdk
JDK15的新特性
JEP 385 Deprecate RMI Activation for Removal
RMI Activation被标记为Deprecate,将会在未来的版本中删除。
RMI大家应该都清楚,RMI就是Remote Method Invocation,翻译成中文就是远程方法调用,是在JDK1.2中引入的。
RMI为java提供了开发分布式系统的强大能力。而J2EE的规范EJB就是使用RMI来实现的bean的远程调用的。
在RMI系统中,远程系统中存在很多分布式对象,如果这些分布式对象一直处于活动状态的话,将会占用很多宝贵的系统资源。
于是RMI引入了一种lazy Activation的方式,这种方式就叫做延迟激活。
这里有两个概念,活动对象和被动对象。
活动对象是在某些系统上的JVM中实例化并对外暴露的远程对象。被动对象是尚未在JVM中实例化(或暴露)但可以进入主动状态的对象。
将被动对象转换为主动对象的过程称为激活。激活要求对象与JVM关联,这可能会将该对象的类加载到JVM中,并且将该对象恢复为之前的状态。
在RMI系统中,我们使用延迟激活。延迟激活将激活对象推迟到客户第一次使用(即第一次方法调用)之前。
既然RMI Activation这么好用,为什么要废弃呢?
因为对于现代应用程序来说,分布式系统大部分都是基于Web的,web服务器已经解决了穿越防火墙,过滤请求,身份验证和安全性的问题,并且也提供了很多延迟加载的技术。
所以在现代应用程序中,RMI Activation已经很少被使用到了。并且在各种开源的代码库中,也基本上找不到RMI Activation的使用代码了。
为了减少RMI Activation的维护成本,在JDK8中,RMI Activation被置为可选的。现在在JDK15中,终于可以废弃了。
JEP 371 Hidden Classes
Hidden Classes是什么呢?
Hidden Classes就是不能直接被其他class的二净值代码使用的class。Hidden Classes主要被一些框架用来生成运行时类,但是这些类不是被用来直接使用的,而是通过反射机制来调用。
通常来说基于JVM的很多语言都有动态生成类的机制,这样可以提高语言的灵活性和效率。
比如在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动态生成相应的类对象。
另外使用动态代理也可以为某些类生成新的动态类。
那么我们希望这些动态生成的类需要具有什么特性呢?
-
不可发现性。因为我们是为某些静态的类动态生成的动态类,所以我们希望把这个动态生成的类看做是静态类的一部分。所以我们不希望除了该静态类之外的其他机制发现。
-
访问控制。我们希望在访问控制静态类的同时,也能控制到动态生成的类。
-
生命周期。动态生成类的生命周期一般都比较短,我们并不需要将其保存和静态类的生命周期一致。
但是现有的类的定义API ClassLoader::defineClass和Lookup::defineClass是不管类的字节码是如何生成的,他们都是平等对待。
所以我们需要一些API来定义无法发现的且具有有限生命周期的隐藏类。这将提高所有基于JVM的语言实现的效率。
比如:
java.lang.reflect.Proxy可以定义隐藏类作为实现代理接口的代理类。
java.lang.invoke.StringConcatFactory可以生成隐藏类来保存常量连接方法;
java.lang.invoke.LambdaMetaFactory可以生成隐藏的nestmate类,以容纳访问封闭变量的lambda主体;
JavaScript引擎可以为从JavaScript程序转换的字节码生成隐藏的类,因为当引擎不再使用它们时,这些类将被卸载。
普通类是通过调用ClassLoader::defineClass创建的,而隐藏类是通过调用Lookup::defineHiddenClass创建的。
这使JVM从提供的字节中派生一个隐藏类,链接该隐藏类,并返回提供对隐藏类的反射访问的查找对象。
调用程序可以通过返回的查找对象来获取隐藏类的Class对象。
JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)
实现了EdDSA椭圆曲线签名算法。
这里就不多讲椭圆曲线签名算法了,如果又想了解的朋友可以给我留言。
JEP 375 Pattern Matching for instanceof (Second Preview)
Pattern Matching 就是说可以在做pattern mathching的时候,直接对该对象进行类型的转换。
现在这个特性还是预览版本的。
我们看一下具体的例子:
if (obj instanceof String) {
String s = (String) obj;
// use s
}
在Pattern Matching之前,我们使用instanceof之后,还需要对该对象进行强制类型转换才能使用。
但是在Pattern Matching之后,我们可以这样用:
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
是不是很方便。
JEP 384 Records (Second Preview)
Record是一种轻量级的class,可以看做是数据结构体。和scala中的case有点相似。
举个自定义User的例子看一下Record是怎么用的:
public record Address(
String addressName,
String city
) {
}
public record CustUser(
String firstName,
String lastName,
Address address,
int age
) {}
上面我们定义了两个类,CustUser和Address。CustUser中引用了Address。
Record和普通的类的区别就在于Record多了一个括号括起来的定义的字段。
Record类默认是final的,里面的字段默认是private final的。
要想知道Record到底是怎么工作的,我们可以使用javap来对编译好的class文件反编译,运行javap CustUser,可以得到下面的结果:
警告: 二进制文件CustUser包含com.flydean.records.CustUser
Compiled from "CustUser.java"
public final class com.flydean.records.CustUser extends java.lang.Record {
public com.flydean.records.CustUser(java.lang.String, java.lang.String, com.flydean.records.Address, int);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public java.lang.String firstName();
public java.lang.String lastName();
public com.flydean.records.Address address();
public int age();
}
上面可以看到final class CustUser继承自java.lang.Record。
并且自动添加了默认带有所有字段的构造函数。各个自动的获取方法,并实现了toString,hashCode和equals方法。
天啦,太完美了,我们想要的它居然都有。
如果上面的javap还不是很清楚的话,大家可以借助IDE的反编译功能,打开CustUser.class文件看一看:
public final class CustUser extends java.lang.Record {
private final java.lang.String firstName;
private final java.lang.String lastName;
private final com.flydean.records.Address address;
private final int age;
public CustUser(java.lang.String firstName, java.lang.String lastName, com.flydean.records.Address address, int age) { /* compiled code */ }
public java.lang.String toString() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public java.lang.String firstName() { /* compiled code */ }
public java.lang.String lastName() { /* compiled code */ }
public com.flydean.records.Address address() { /* compiled code */ }
public int age() { /* compiled code */ }
}
注意,上面的反编译我们可以看到,record中的所有字段都是final的,只能在初始化的时候设置。并且方法里面也没有提供其他可以改变字段内容的方法。
所以我们得出了一个震世惊俗的结论:record是immutable的。
上面的例子中我们只使用了小括号里面的内容,大括号还是空的呀。可不可以像其他正常的类一样,添加点方法或者构造函数进去呢?
答案是肯定的。
先看一个整体的方案:
public record CustUserWithBody(
String firstName,
String lastName,
Address address,
int age
) {
public String fullName(){
return firstName+ lastName;
}
public CustUserWithBody{
if (age < 18) {
throw new IllegalArgumentException( "男大当婚,女大当嫁,18岁未到,不许出嫁!");
}
}
}
我们在record的主题中,定义了一个方法和一个构造函数。
先看这个方法,在方法中我们可以访问到record中定义的变量,但是千万不要尝试去修改他们,因为他们是final的,你会得到一个变异错误。
再看这个构造函数,这个构造函数没有小括号,只有大括号,这种构造函数叫做Compact constructor。你无法在record中定义正常的构造函数,因为会得到一个编译错误。
在这个Compact constructor中,我们可以对定义的字段进行数据校验。如上所述。
JEP 360 Sealed Classes (Preview)
在Java中,类层次结构通过继承实现代码的重用,父类的方法可以被许多子类继承。
但是,类层次结构的目的并不总是重用代码。有时,其目的是对域中存在的各种可能性进行建模,例如图形库支持的形状类型或金融应用程序支持的贷款类型。
当以这种方式使用类层次结构时,我们可能需要限制子类集从而来简化建模。
因为我们引入了sealed class或interfaces,这些class或者interfaces只允许被指定的类或者interface进行扩展和实现。
举个例子:
package com.example.geometry;
public abstract sealed class Shape
permits Circle, Rectangle, Square {...}
上面的例子中,我们指定了Shape只允许被Circle, Rectangle, Square来继承。
上面的例子中并没有指定类的包名,我们可以这样写:
package com.example.geometry;
public abstract sealed class Shape
permits com.example.polar.Circle,
com.example.quad.Rectangle,
com.example.quad.simple.Square {...}
JEP 378 Text Blocks
Text Blocks是为了解决在java中输入多行数据的问题。
比如:
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
可以写成:
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
可以写成:
String query = """
SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
WHERE "CITY" = 'INDIANAPOLIS'
ORDER BY "EMP_ID", "LAST_NAME";
非常的方便。
Java14新特性
1、Switch(最终版)
和之前的jdk12、13功能一样,只不过确定下来为最终版
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
2、垃圾回收器(更新优化)
1、Windows的ZGC:现在可以在Windows上作为实验功能使用,要启用它,请使用JVM标志-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC。
2、Mac的ZGC:现在可作为macOS上的实验功能使用。要启用它,请使用JVM标志-XX:+UnlockExperimentalVMOptions -XX:+UseZGC。
3、并行GC的改进:并行GC已采用与其他收集器相同的任务管理机制来调度并行任务。这可能会显着提高性能。由于这一变化,以下产品标志
已过时:-XX:BindGCTaskThreadsToCPUs,-XX:UseGCTaskAffinity,和-XX:GCTaskTimeStampEntries。
4、G1 NUMA感知内存分配:现在尝试跨垃圾收集在年轻一代的同一NUMA节点上分配并保留对象。这类似于并行GC NUMA意识。G1尝试使用
严格的交错在所有可用的NUMA节点上均匀分配Humongous和Old区域。从年轻一代复制到老一代的对象的放置是随机的。这些新的NUMA感知
内存分配试探法通过使用-XX:+UseNUNMA命令行选项自动启用。
3、Record(预览功能)
@Data
@AllArgsConstructor
class Group {
// 组名
private String name;
// 人数
private int nums;
}
使用它可以替代构造器、equal方法、toString方法,hashCode方法
Point(String name,int nums){}
Java语言中一种新型的类型声明。像枚举一样enum, record是类的受限形式。它声明其表示形式,并提交与该表示形式匹配的API。记录放弃了类通常享有的自由:将API与表示分离的能力。作为回报,记录获得了很大程度的简洁性。
4、
可以通过 NumberFormat.getCurrencyInstance(Locale)使用“ u-cf-account” Unicode区域设置扩展名来获得具有记帐样式的
货币格式实例,其中金额在某些区域设置中用括号表示,例如,Locale.US,它将格式化为($3.27)而不是-$3.27。
而之前的版本是前边结果为负数。
5、NIO的Channel通道
阐明ReadableByteChannel.read()的规范和规格DatagramChannel.receive(),FileChannel.read(ByteBuffer,long),Read
ableByteChannel.read(),ScatteringByteChannel.read()方法已经在此版本已经更新到指定的IllegalArgumentException,如果
(任何)缓冲区参数(S)是只读的抛出。
6、删除功能
1、CMS垃圾收集器已被删除。-XX:UseConcMarkSweepGC和别名-Xconcgc,-Xnoconcgc以及所有CMS特定选项(太多,无法列出)都已废弃。
2、删除了安全库java.security.acl API
7、
提供模式匹配来 增强Java编程语言instanceof
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
不建议使用线程挂起、删除,下面的方法中涉及的线程挂起Thread,并且Thread已在本版本中晚期弃用,Thread.suspend(),Thread.
resume(),ThreadGroup.suspend(),ThreadGroup.resume(),ThreadGroup.allowThreadSuspension(boolean)这些方法将在
将来的版本中删除。
弃用ParallelScavenge + SerialOld GC组合,任何UseParallelOldGC用于启用此垃圾回收算法组合的命令行选项的使用,都会引
起弃用警告。嵌入式替换是通过-XX:+UseParallelGC在命令行上使用ParallelScavenge + ParallelOld垃圾收集器。
security-libs / javax.crypto,已过时的旧椭圆曲线去除。
9、注意点
该规范java.lang.Thread::interrupt允许实现仅跟踪活动线程的中断状态,并且以前就是这种情况。从此版本开始,a的中断状态
Thread始终可用,并且如果您在线程t启动之前或终止之后中断线程,查询t.isInterrupted()将返回true。
如果套接字未连接且没有套接字地址,send则由DatagramSocket和定义的方法MulticastSocket已更改为抛出。
该MulticastSocket方法getOption已更改为符合中描述的行为StanndardSocketOptions.IP_MULTCAST_IF。如果没有设置接口,
MulticastSocket.getOption(StanndardSocketOptions.IP_MULTCAST_IF)现在返回null。
该MulticastSocket方法getOption和setOption已更改以符合所描述的行为StandardSocketOptions.IP_MULTICAST_LOOP规范,
MulticastSocket.getOption(StanndardSocketOptions.IP_MULTCAST_IF)现在,如果启用了环回模式,则返回true。
设置MulticastSocket.getOption(StanndardSocketOptions.IP_MULTCAST_IF)启用回送模式。
Java13新特性
1、switch优化更新(预览版)
什么是预览版,也就是说当前版本有这个功能,下一个版本不确定会有,如果该功能效果不是很好,会被下一版本移除该功能。
JDK11以及之前的版本
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break; case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}
JDK12版本
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
JDK13版本,可以返回信息
@Test
void test1() {
int k = 2;
String result = switch (k) {
case 1 -> "one";
case 2 -> "two";
default -> "many";
};
System.out.println(result);
}
2、文本块升级
2.1、html例子
JDK13之前
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
JDK13优化
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
2.2、SQL变化
JDK13之前
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
"WHERE `CITY` = 'INDIANAPOLIS'\n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;\n";
JDK13
String query = """
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";
2.3、解释
文本块
"""
line 1
line 2
line 3
"""
相当于字符串文字:
"line 1\nline 2\nline 3\n"
3、动态CDS档案
目标:
提高应用程序类 - 数据共享(AppCDS)的可用性。消除了用户进行试运行以创建每个应用程
序的类列表的需要。-Xshare:dump使用类列表由该选项启用的静态归档应继续工作。这包括内置类
加载器和用户定义的类加载器的类。
4、取消使用未使用的内存
摘要:
增强ZGC以将未使用的堆内存返回给操作系统。
动机:
ZGC目前没有取消提交并将内存返回给操作系统,即使该内存长时间未使用。对于所有类型的应用
程序和环境,此行为并非最佳,尤其是那些需要关注内存占用的应用程序和环境 例如:通过使用支付资
源的容器环境。应用程序可能长时间处于空闲状态并与许多其他应用程序共享或竞争资源的环境。应用
程序在执行期间可能具有非常不同的堆空间要求。
例如,启动期间所需的堆可能大于稳态执行期间稍后所需的堆。HotSpot中的其他垃圾收集器,如
G1和Shenandoah,提供了这种功能,某些类别的用户发现它非常有用。将此功能添加到ZGC将受到同一
组用户的欢迎。
5、重新实现旧版套接字API
摘要:
使用更简单,更现代的实现替换java.net.Socket和java.net.ServerSocketAPI使用的底层实现,
易于维护和调试。新的实现很容易适应用户模式线程,也就是光纤,目前正在Project Loom中进行探索。
动机:
在java.net.Socket和java.net.ServerSocketAPI,以及它们的底层实现,可以追溯到JDK1.0。
实现是遗留Java和C代码的混合,维护和调试很痛苦。该实现使用线程堆栈作为I/O缓冲区,这种方法需要多
次增加默认线程堆栈大小。该实现使用本机数据结构来支持异步关闭,这是多年来微妙可靠性和移植问题的根
源。该实现还有几个并发问题,需要进行大修才能正确解决。在未来的光纤世界环境中,而不是在本机方法中
阻塞线程,当前的实现不适用于目的。
6、
核心库/ java.nio中添加了FileSystems.newFileSystem(Path,Map <String,?>)方法
添加了三种新方法java.nio.file.FileSystems
,以便更轻松地使用将文件内容视为文件系统的文件系统提供程序。
1、newFileSystem(Path)
2、newFileSystem(Path, Map<String, ?>)
3、newFileSystem(Path, Map<String, ?>, ClassLoader) 添加为newFileSystem(Path, Map<String, ?>) 已使用现有2-arg newFileSystem(Path,
ClassLoader)并指定类加载器的代码创建源(但不是二进制)兼容性问题。例如,由于引用
newFileSystem不明确,因此无法编译以下内容: FileSystem fs = FileSystems.newFileSystem(path, null),
为了避免模糊引用,需要修改此代码以将第二个参数强制转换为java.lang.ClassLoader。
7、nio新方法
核心库/ java.nio中新的java.nio.ByteBuffer批量获取/放置方法转移字节而不考虑缓冲区位置。
java.nio.ByteBufferjava.nio现在,其他缓冲区类型定义绝对批量get和put传输连续字节序列的方法,而不考虑或影响缓冲区位置。
8、核心库/ java.time
新日本时代名称Reiwa,此更新中添加了代表新Reiwa时代的实例。与其他时代不同,这个时代没有公共
领域。它可以通过调用JapaneseEra.of(3)或获得JapaneseEra.valueOf("Reiwa")。JDK13及更高版
本将有一个新的公共领域来代表这个时代。
NewEra从2019年5月1日开始的日本时代的占位符名称“ ”已被新的官方名称取代。依赖占位符名称获取
新时代单例(JapaneseEra.valueOf("NewEra"))的应用程序将不再起作用。
9、核心库/ java.util中:I18N
支持Unicode 12.1,此版本将Unicode支持升级到12.1,其中包括以下内容:
java.lang.Character支持12.1级的Unicode字符数据库,其中12.0从11.0开始增加554个字符,
总共137,928个字符。这些新增内容包括4个新脚本,总共150个脚本,以及61个新的表情符号字符。
U+32FF SQUARE ERA NAME REIWA从12.0开始,12.1只添加一个字符。java.text.Bidi和
java.text.Normalizer类分别支持12.0级的Unicode标准附件,#9和#15。
java.util.regexpackage支持基于12.0级Unicode标准附件#29的扩展字形集群。
10、热点/ GC
10.1 JEP 351 ZGC取消提交未使用的存储器
10.2 添加了-XXSoftMaxHeapSize标志
10.3 ZGC支持的最大堆大小从4TB增加到16TB
11、安全库/ java.security
11.1 该com.sun.security.crl.readtimeout系统属性设置为CRL检索的最大读取超时,单位为秒。
如果尚未设置该属性,或者其值为负,则将其设置为默认值15秒。值0表示无限超时。
11.2 新的keytool -showinfo -tls用于显示TLS配置信息的命令keytool -showinfo -tls添加
了一个显示TLS配置信息的新命令。
11.3 SunMSCAPI提供程序现在支持以下一代加密(CNG)格式读取私钥。这意味着CNG格式的RSA和EC
密钥可从Windows密钥库加载,例如“Windows-MY”。与EC(签名算法SHA1withECDSA,SHA256withECDSA等等)也支持。
12、删除功能
删除的部分功能:
12.1 核心库/java.net中,不再支持Pre-JDK 1.4 SocketImpl实现java.net.SocketImpl此版本已删除对为
JavaSE1.3及更早版本编译的自定义实现的支持。此更改对SocketImpl为Java SE 1.4(2002年发布)或更新版本编译
的实现没有影响。
12.2 核心库/java.lang中,删除运行时跟踪方法,过时的方法traceInstructions(boolean),并
traceMethodCalls(boolean)已经从删除java.lang.Runtime类。这些方法对许多版本都不起作用,它们
的预期功能由Java虚拟机工具接口(JVMTI)提供。
Java12新特性
1、JDK12之Shenandoah低暂停时间垃圾收集器(实验性)
定义:
添加一个名为Shenandoah的新垃圾收集(GC)算法,通过与正在运行的Java线程同时进行疏散工作
来减少GC暂停时间。使用Shenandoah的暂停时间与堆大小无关,这意味着无论堆是200MB还是200GB,都
将具有相同的一致暂停时间。
非目标:
这不是一个统治所有人的GC。还有其他垃圾收集算法可以优先考虑吞吐量或内存占用而不是响应性。
Shenandoah是适用于评估响应性和可预测的短暂停顿的应用程序的算法。目标不是解决所有JVM暂停问
题。由于GC之外的其他原因(例如安全时间点(TTSP)发布或监控通胀)而暂停时间超出了此JEP的范围。
构建和调用:
作为实验性功能,Shenandoah将-XX:+UnlockExperimentalVMOptions在命令行中要求。Shenandoah构建系统会自动禁用不受
支持的配置。下游建设者可以选择--with-jvm-features=-shenandoahgc在其他支持的平台上禁用构建Shenandoah。
要启用/使用Shenandoah GC,需要以下JVM选项:-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
2、JDK12之Microbenchmark Suite
定义:
在JDK源代码中添加一套基本的微基准测试,使开发人员可以轻松运行现有的微基准测试并创
建新的基准测试。
目标:
1、基于[Java Microbenchmark线束(JMH)] [1]
2、稳定且经过调整的基准测试,针对持续性能测试
2.1、在功能发布的功能完成里程碑之后,以及非功能版本之后的稳定且不移动的套件
2.2、支持与先前JDK版本的适用测试比较
3、简单
3.1 轻松添加新基准
3.2 在API和选项更改,不推荐使用或在开发期间删除时,可以轻松更新测试
3.3 易于构建
3.4 易于查找和运行基准
3.5 支持JMH更新
3.6 在套件中包含大约一百个基准的初始集
3、JDK12之Switch表达式(预览版)
预览功能,如果该jdk12的switch效果不好的话,会被下一版本jdk13直接移除该功能,并不是之后每个版本必须的。
许多break使它不必要地冗长,如果忘记写break,则会产生意料之外的结果或者异常,所以针对于此jdk12在这里进行了优化升级。
JDK12之前的版本:
switch (day) { case MONDAY: case FRIDAY: case SUNDAY: System.out.println(6); break; case TUESDAY: System.out.println(7); break; case THURSDAY: case SATURDAY: System.out.println(8); break; case WEDNESDAY: System.out.println(9); break; }
JDK12:我们建议引入一种新形式的开关标签,写成“case L ->”表示如果标签匹配,则只执行标签右侧的代码。
switch (day) { case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); case TUESDAY -> System.out.println(7); case THURSDAY, SATURDAY -> System.out.println(8); case WEDNESDAY -> System.out.println(9); }
许多Switch表达式,每个case都会赋值给一个变量或者执行某种操作,如下是赋值给numLetters变量具体值。
JDK12之前:
int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalStateException("Wat: " + day); }
JDK12:将此表达为一种陈述是迂回的,重复的,并且容易出错。意味着我们应该计算numLetters每一天的价值。应该可以直接说,使用更清晰,更安全Switch表达式
int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; };
如果将它用在方法上,则可以为:
static void howMany(int k) { switch (k) { case 1 -> System.out.println("one"); case 2 -> System.out.println("two"); case 3 -> System.out.println("many"); } }
或者类上,我想到的这个switch这个功能可以用在抽象工厂类方面。
T result = switch (arg) { case L1 -> e1; case L2 -> e2; default -> e3; };
4、JDK12之JVM常量API
摘要:
引入API来模拟关键类文件和运行时工件的名义描述,特别是可从常量池加载的常量。
动机:
每个Java类文件都有一个常量池,用于存储类中字节码指令的操作数。从广义上讲,常量池中的条目描述了运行
时工件(如类和方法)或简单值(如字符串和整数)。所有这些条目都称为可加载常量,因为它们可以作为ldc指令的
操作数(“加载常量”)。
它们也可能出现在invokedynamic指令的bootstrap方法的静态参数列表中。执行一个ldc或invokedynamic指令
导致加载常数被解析成一个标准的Java类,如“活”的值Class,String或int。
操作class文件的程序需要对字节码指令进行建模,并依次对可加载的常量进行建模。但是,使用标准Java类型
来模拟可加载常量是不合适的。
描述字符串(CONSTANT_String_info条目)的可加载常量可能是可以接受的,因为生成“实时” String对象
很简单,但是对于描述类(CONSTANT_Class_info条目)的可加载常量是有问题的,因为产生“实时”ClassObject
依赖于类加载的正确性和一致性。
不幸的是,类加载有许多环境依赖和失败模式:所需的类不存在或者请求者可能无法访问; 类加载的结果因上下文
而异; 装载类有副作用;有时类加载可能根本不可能(例如当所描述的类尚不存在或者无法加载时,如在编译那些相同类
或在jlink转换期间)。
因此,处理可加载常量的程序如果能够以纯粹的名义符号形式操作类和方法,以及不太知名的工件(如方法句柄和动
态计算常量),则会更简单:
1、字节码解析和生成库必须以符号形式描述类和方法句柄。如果没有标准机制,它们必须采用ad-hoc机制,无论是
ASM的描述符类型Handle,还是字符串元组(方法所有者,方法名称,方法描述符),或者这些机制的特殊(并且容易出
错)编码单个字符串。
2、如果它们可以在符号域中工作而不是使用“实时”类和方法句柄,invokedynamic那么通过旋转字节码(例如LambdaMetafactory)来操作的Bootstraps 将更简单。
3、编译器和脱机转换器(例如jlink插件)需要描述无法加载到正在运行的VM的类的类和成员。编译器插件(例如注
释处理器)同样需要用符号术语来描述程序元素。
5、JDK12之一个AArch64端口,而不是两个
摘要:
arm64在保留32位ARM端口和64位aarch64端口的同时,删除与端口相关的所有源。
动机:
删除此端口将允许所有贡献者将他们的精力集中在单个64位ARM实现上,并消除维护两个端口所需的重复工作。
6、JDK12之默认CDS档案
摘要:
在64位平台上使用默认类列表增强JDK构建过程以生成类数据共享(CDS)归档。
目标:
1、改善开箱即用的启动时间
2、消除用户运行-Xshare:dump以从CDS中受益的需要
7、JDK12之G1的可流动混合收集
摘要:
如果G1混合集合可能超过暂停目标,则使其可以中止。
动机:
G1的目标之一是满足用户提供的暂停时间目标以暂停其收集暂停。G1使用高级分析引擎来选择在集合期间
要完成的工作量(这部分基于应用程序行为)。此选择的结果是一组称为集合集的区域。一旦确定了集合集并且
已经开始集合,则G1必须在不停止的情况下收集集合集的所有区域中的所有活动对象。如果启发式选择过大的收
集,则此行为可导致G1超过暂停时间目标,例如,如果应用程序的行为发生变化,以致启发式工作在“陈旧”数据
上,则可能发生这种情况。特别是在混合集合期间可以观察到这种情况,其中集合集通常可以包含太多旧区域。
需要一种机制来检测启发式方法何时反复为集合选择错误的工作量,如果是,则让G1逐步递增地执行收集工作,
其中集合可以在每个步骤之后中止。这种机制将允许G1更频繁地满足暂停时间目标。
8、JDK12之从G1中立即返回未使用的已提交内存
摘要:
增强G1垃圾收集器,以便在空闲时自动将Java堆内存返回给操作系统。
成功指标:
如果应用程序活动非常低,G1应该在合理的时间段内释放未使用的Java堆内存。
动机:
目前G1垃圾收集器可能无法及时将已提交的Java堆内存返回给操作系统。G1仅在完整GC或并发周期内
从Java堆返回内存。由于G1很难完全避免完整的GC,并且只触发基于Java堆占用和分配活动的并发周期,
因此在许多情况下它不会返回Java堆内存,除非在外部强制执行此操作。
在使用资源支付的容器环境中,这种行为特别不利。即使在VM由于不活动而仅使用其分配的内存资源的
一小部分的阶段,G1也将保留所有Java堆。这导致客户始终为所有资源付费,云提供商无法充分利用其硬件。
如果VM能够检测到Java堆的利用率不足(“空闲”阶段),并在此期间自动减少其堆使用量,则两者都
将受益。
Shenandoah和OpenJ9的GenCon收集器已经提供了类似的功能。
9、核心库java.lang中支持Unicode11
JDK 12版本包括对Unicode 11.0.0的支持。在发布支持Unicode 10.0.0的JDK 11之后,Unicode 11.0.0引入了以下JDK 12中包含的新功能:
1、684个新角色
1.1、66个表情符号字符
1.2、Copyleft符号
1.3、评级系统的半星
1.4、额外的占星符号
1.5、象棋中国象棋符号
2、11个新区块
2.1、格鲁吉亚扩展
2.2、玛雅数字
2.3、印度Siyaq数字
2.4、国际象棋符号
3、7个新脚本
3.1、Hanifi Rohingya
3.2、Old Sogdian
3.3、Sogdian
3.4、Dogra
3.5、Gunjala Gondi
3.6、Makasar
3.7、Medefaidrin
10、核心库java.text支持压缩数字格式
NumberFormat添加了对以紧凑形式格式化数字的支持。紧凑数字格式是指以简短或人类可
读形式表示的数字。例如,在en_US语言环境中,1000可以格式化为“1K”,1000000可以格式化
为“1M”,具体取决于指定的样式NumberFormat.Style。紧凑数字格式由LDML的Compact
Number格式规范定义。要获取实例,请使用NumberFormat紧凑数字格式所给出的工厂方法之一。 例如:NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000); 上面的例子导致“1K”。
12、安全库java.security
禁止并允许java.security.manager系统属性的选项
新的“disallow”和“allow”令牌选项已添加到java.security.manager系统属性中。
在JDK实现中,如果Java虚拟机以系统属性java.security.manager设置为“disallow”开始,
则该System.setSecurityManager方法不能用于设置安全管理器并将抛出
UnsupportedOperationException。“disallow”选项可以提高从未设置安全管理器的应用程
序的运行时性能。
groupname选项添加到keytool密钥对生成
-groupname添加了一个新选项,keytool -genkeypair以便用户在生成密钥对时可以指
定命名组。例如,keytool -genkeypair -keyalg EC -groupname secp384r1将使用
secp384r1曲线生成EC密钥对。由于可能存在多个具有相同大小的曲线,因此使用该-groupname
选项优先于该-keysize选项。
新Java飞行记录器(JFR)安全事件
略过...
自定义PKCS12密钥库生成
添加了新的系统和安全属性,使用户能够自定义PKCS#12密钥库的生成。这包括用于密钥保护,
证书保护和MacData的算法和参数。可以在文件的“PKCS12 KeyStore属性”部分中找到这些属性的
详细说明和可能的值java.security。
13、安全库javax.net.ssl
ChaCha20和Poly1305 TLS密码
JSSE中添加了使用ChaCha20-Poly1305算法的新TLS密码套件。默认情况下启用这些密码套件。
TLS_CHACHA20_POLY1305_SHA256密码套件适用于TLS 1.3。
14、安全库/ org.ietf.jgss
在krb5.conf中支持dns_canonicalize_hostname
该dns_canonicalize_hostname标志中krb5.conf的配置文件现在是由JDK Kerberos实现支持。
设置为“true”时,服务主体名称中的短主机名将被规范化为完全限定的域名(如果可用)。否则,不执行规
范化。默认值是true”。这也是JDK 12之前的行为。
15、删除项
核心库/ java.util.jar中,删除java.util.ZipFile / Inflator / Deflator中的finalize方法
该finalize方法在java.util.ZipFile,java.util.Inflator和java.util.Deflator是在JDK9
弃用用于移除及其执行了更新,是一个空操作。该finalize在方法java.util.ZipFile,java.util.Inflator
以及java.util.Deflator在此版本中被删除。finalize应修改为执行清理而重写的子类,以使用备用清理机制并
删除写finalize方法。
finalize方法,去除将暴露Object.finalize到的子类ZipFile,Deflater和Inflater。finalize由于
声明的异常发生更改,可能会在覆盖时发生编译错误。Object.finalize现在宣布投掷java.lang.Throwable。
以前,只有java.io.IOException宣布。
核心库/ java.io,从FileInputStream和FileOutputStream中删除finalize方法
该finalize方法FileInputStream和FileOutputStream被弃用去除JDK 9.他们已经在此版本中被删除。
所述java.lang.ref.Cleaner,自JDK9的主要机制已被实施,以关闭文件描述符不再从可到达的FileInputStream和FileOutputStream。关闭文件的推荐方法是显式调用close或使用try-with-resources。
工具/ javac的删除javac支持6 / 1.6源,目标和发布值
为的javac的6/1.6的参数值的支持-source,-target以及--release标志已被删除。
Java11新特性
1、增强局部变量类型推断var
Consumer<String> consumer = t -> System.out.println(t.toUpperCase()); Consumer<String> consumer = (var t) -> System.out.println(t.toUpperCase()); 错误的形式:必须要有类型,可以加上var Consumer<String> consumer = (@Deprecated t) ->System.out.println(t.toUpperCase()) 正确的形式 Consumer<String> consumer = (@Deprecated var t) ->System.out.println(t.toUpperCase())
2、增加一些实用的API
自JDK9和JDK10都为java增加了许多的API,如今JDK11又增加了许多字符串自带方法,如下
@Test public void contextLoads() { String str = "woshidage"; boolean isblank = str.isBlank(); //判断字符串是空白 boolean isempty = str.isEmpty(); //判断字符串是否为空 String result1 = str.strip(); //首位空白 String result2 = str.stripTrailing(); //去除尾部空白 String result3 = str.stripLeading(); //去除首部空白 String copyStr = str.repeat(2); //复制几遍字符串 long lineCount = str.lines().count(); //行数统计 System.out.println(isblank); System.out.println(isempty); System.out.println(result1); System.out.println(result2); System.out.println(result3); System.out.println(copyStr); System.out.println(lineCount); }
结果为:
3、移除和废弃的内容
3.1 移除项
1、移除了com.sun.awt.AWTUtilities
2、移除了sun.misc.Unsafe.defineClass,使用java.lang.invoke.MethodHandles.Lookup.defineClass来替代
3、移除了Thread.destroy()以及 Thread.stop(Throwable)方法
4、移除了sun.nio.ch.disableSystemWideOverlappingFileLockCheck、sun.locale.formatasdefault属性
5、移除了jdk.snmp模块
6、移除了javafx,openjdk估计是从java10版本就移除了,oracle jdk10还尚未移除javafx,而java11版本则oracle的jdk版本也移除了javafx
7、移除了Java Mission Control,从JDK中移除之后,需要自己单独下载
8、移除了这些Root Certificates :Baltimore Cybertrust Code Signing CA,SECOM ,AOL and Swisscom
3.2 废弃项
1、-XX+AggressiveOpts选项
2、-XX:+UnlockCommercialFeatures
3、-XX:+LogCommercialFeatures选项也不再需要
4、HttpClient加强方法
现在 Java 自带了这个 HTTP Client API,我们以后还有必要用 Apache 的 HttpClient 工具包吗?
4.1 需要远程调用的接口
@RequestMapping(value = "/dshjbca") public String test1(){ return "dfs"; }
4.2 HttpClient调用该接口
//同步调用 @Test public void test2() throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder(URI.create("")).build(); BodyHandler<String> handler = HttpResponse.BodyHandlers.ofString(); HttpResponse<String> response = client.send(request,handler); String body = response.body(); System.out.println(body); } //异步调用 @Test public void test3() throws IOException, InterruptedException, ExecutionException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder(URI.create("")).build(); BodyHandler<String> handler = HttpResponse.BodyHandlers.ofString(); CompletableFuture<HttpResponse<String>> response = client.sendAsync(request,handler); HttpResponse<String> result = response.get(); String body = result.body(); System.out.println(body); }
结果:
5、Unicode 10
Unicode 10 增加了8518个字符, 总计达到了136690个字符. 并且增加了4个脚本.同时还有56个新的emoji表情符号。
6、Remove the JavaEE and CORBA Moudles
在java11中移除了不太使用的JavaEE模块和CORBA技术,在java11中将java9标记废弃的Java EE及CORBA模块移除掉。
1、java.xml.ws,
2、java.xml.bind,
3、java.xml.ws,
4、java.xml.ws.annotation,
5、jdk.xml.bind,
6、jdk.xml.ws被移除,
只剩下java.xml,java.xml.crypto,jdk.xml.dom这几个模块
7、java.corba,
8、java.se.ee,
9、java.activation,
10、java.transaction被移除,但是java11新增一个java.transaction.xa模块
7、JEP : 335 : Deprecate the Nashorn JavaScript Engine
废除Nashorn javascript引擎,在后续版本准备移除掉,有需要的可以考虑使用GraalVM。
8、JEP : 336 : Deprecate the Pack200 Tools and API
Java5中带了一个压缩工具:Pack200,这个工具能对普通的jar文件进行高效压缩。其 实现原理是根据Java类特有的结构,合并常数 池,去掉无用信息等来实现对java类的高效压缩。由于是专门对Java类进行压缩的,所以对普通文件的压缩和普通压缩软件没有什么两样,但是对于Jar 文件却能轻易达到10-40%的压缩率。这在Java应用部署中很有用,尤其对于移动Java计算,能够大大减小代码下载量。
Java5中还提供了这一技术的API接口,你可以将其嵌入到你的程序中使用。使