JDk12~16新特性
JDK 12 的新特性
JDK12 于 2019 年 3 月发布
1. Switch 表达式(预览特性)
JDK 12 引入了 switch
表达式,作为传统 switch
语句的增强版。switch
表达式可以返回值,并且支持新的 case
标签格式。这一特性目前是作为预览功能提供的,可能会在未来的版本中进行进一步调整。
public class SwitchExpressionExample {
public static void main(String[] args) {
int dayOfWeek = 3;
// `switch` 表达式使用 `->` 语法简化了代码,并返回了一个值 `dayName`。
String dayName = switch (dayOfWeek) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default -> throw new IllegalArgumentException("Invalid day: " + dayOfWeek);
};
System.out.println("The day is: " + dayName);
}
}
2. G1 垃圾回收器改进
JDK 12 对 G1 垃圾回收器进行了改进,使得 G1 可以自动回收未使用的类。这项增强功能减少了元空间的内存占用,从而提升了垃圾回收的效率。
# 启用 G1 GC 并自动回收未使用的类
java -XX:+UseG1GC -XX:+ClassUnloadingWithConcurrentMark -jar myapp.jar
这项改进对内存管理有显著的优化效果,尤其是对长期运行的应用程序。
3. Shenandoah 垃圾回收器(实验性)
JDK 12 引入了 Shenandoah 垃圾回收器,它是一种低暂停时间的垃圾回收器,适用于需要极低延迟的应用场景。Shenandoah 通过在收集期间并发移动活跃对象,最大限度地减少了停顿时间。
# 使用 Shenandoah GC 运行应用
java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -jar myapp.jar
Shenandoah GC 适用于对延迟敏感的应用,如金融系统和高性能计算应用。
原始字符串字面量提供了更好的代码可读性,尤其是在处理多行文本时。
4. 数字格式化工具类 Compact Number Formatting
JDK 12 引入了紧凑数字格式化工具,允许根据区域设置以简短形式显示数字。这对需要处理国际化的应用程序非常有用。
import java.text.NumberFormat;
import java.util.Locale;
public class CompactNumberExample {
public static void main(String[] args) {
NumberFormat nf = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
System.out.println(nf.format(1000)); // 输出 "1K"
System.out.println(nf.format(1000000)); // 输出 "1M"
}
}
5. instanceof 增强
Object obj = "String";
if(obj instanceof String str){
System.out.println(str);
}
JDK13 新特性
当然可以!以下是一篇关于 JDK 13 新特性的博客文章,涵盖了主要的改进和新功能。
感谢指出这一点!JDK 13 中确实对 Socket API 进行了重要的改进。这是我之前遗漏的部分。下面我会为你补充关于 JDK 13 中 Socket API 改进的详细内容,并更新完整的博客文章。
探索 JDK 13 的新特性
Java 13 于 2019 年 9 月发布。
1. 增强的文本块(预览)
JDK 13 引入了文本块(Text Blocks)。
public class TextBlockExample {
public static void main(String[] args) {
String textBlock = """
{
"name": "John",
"age": 30,
"city": "New York"
}
""";
System.out.println(textBlock);
}
}
2. Switch 表达式的进一步改进(预览)
JDK 13 对 switch
表达式进行了进一步改进,作为 JDK 12 中引入的预览功能的扩展。新的 switch
表达式支持 yield
语句来返回值,并简化了 case
分支的书写。
return 会直接跳出当前循环或者方法,而 yield 只会跳出当前 Switch 块,同时在使用 yield 时,需要有 default 条件。
public class SwitchExpressionExample {
public static void main(String[] args) {
int dayOfWeek = 3;
String dayName = switch (dayOfWeek) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default: yield dayOfWeek +" 不要瞎写";
};
System.out.println("The day is: " + dayName);
}
}
3. 动态 CDS 档案(Dynamic CDS Archives)
类数据共享(CDS)在 JDK 13 中得到了增强,支持动态档案。动态 CDS 档案允许在应用程序启动时动态生成和加载类数据档案,进一步提高了应用程序的启动速度和内存效率。
# 使用动态 CDS 档案运行应用
java -Xshare:dump -jar myapp.jar
尤其适用于需要快速启动的场景。
4. ZGC 的未使用内存回收
ZGC(Z Garbage Collector)在 JDK 13 中进一步改进,增加了对未使用内存的回收支持。允许 ZGC 回收那些不再使用的内存,减少应用程序的内存占用。
# 使用 ZGC 运行应用并回收未使用的内存
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+ZUncommit -jar myapp.jar
这种增强功能对于需要处理大规模内存的应用程序尤其有用,帮助优化资源利用。
5. 重启的 AArch64 平台端口
JDK 13 重启了对 AArch64(ARM 64 位架构)平台的支持。
# 在 AArch64 平台上运行应用
java -XX:+UseAArch64Intrinsics -jar myapp.jar
6. 改进的启动单文件源代码
JDK 13 进一步改进了对单文件源代码的启动支持,使得直接运行单个 Java 文件更加高效。这对于快速测试和验证代码片段非常有用。
# 直接运行 Java 源文件
java HelloWorld.java
8. FileSystems 的新方法 getFileStore(Path)
JDK 13 为 java.nio.file.FileSystems
添加了新的方法 getFileStore(Path)
,它允许开发者获取文件系统的存储信息。这有助于更方便地管理文件系统的资源。
import java.nio.file.*;
public class FileSystemExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("test.txt");
FileStore fileStore = FileSystems.getDefault().getFileStore(path);
System.out.println("File store: " + fileStore);
}
}
通过这个新方法,开发者可以更好地了解和管理文件系统的使用情况。
9. Socket API 改进
JDK 13 中对传统 Socket API 的重新实现是该版本的主要新功能之一。该项改进旨在提高 Socket API 的性能和稳定性,并为未来的改进奠定基础。
重新实现的主要内容:
- 用新的
NioSocketImpl
实现取代旧的PlainSocketImpl
实现。NioSocketImpl
基于 JDK 内部用于 NIO(New I/O)的相同基础结构,因此无需使用本地代码,并且与现有的缓冲区缓存机制集成在一起,从而无需为 I/O 操作使用线程栈。 - 简化了 Socket API 代码,使其更易于理解和维护。
- 修复了一些已知的错误,并增强了安全性。
具体优势:
- 性能提升: 新的
NioSocketImpl
实现比旧的PlainSocketImpl
实现性能更高,尤其是在高负载情况下。这是因为NioSocketImpl
利用了 NIO 的异步 I/O 模型,可以更有效地利用 CPU 和 I/O 资源。 - 稳定性增强: 新的
NioSocketImpl
实现更加稳定,不易出现错误和异常。这是因为NioSocketImpl
基于 JDK 内部经过良好测试的基础结构,并且在开发过程中进行了大量的测试。 - 可维护性更好: 新的
NioSocketImpl
实现代码更加简洁易懂,注释也更加完善,这使得开发人员更容易理解和维护相关代码。 - 安全性增强: 新的
NioSocketImpl
实现修复了一些已知的安全漏洞,并增强了对安全威胁的防御能力。
JDK14 新特性
JDK 14 于 2020 年 3 月发布,非长期支持(Non-LTS)版本。
1. Switch 表达式(正式发布)
在 JDK 12 和 JDK 13 中作为预览特性引入的 Switch 表达式,在 JDK 14 中得以正式发布。
public class SwitchExpressionExample {
public static void main(String[] args) {
int dayOfWeek = 3;
String dayName = switch (dayOfWeek) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default -> throw new IllegalArgumentException("Invalid day: " + dayOfWeek);
};
System.out.println("The day is: " + dayName);
}
}
2. 文本块(Text Blocks)
文本块作为 JDK 13 的预览特性在 JDK 14 中得到了进一步改进和稳定。
public class TextBlockExample {
public static void main(String[] args) {
String jsonString = """
{
"name": "John",
"age": 30,
"city": "New York"
}
""";
System.out.println(jsonString);
}
}
3. 增强的 NullPointerException
JDK 14 引入了对 NullPointerException 的增强诊断功能。当发生空指针异常时,Java 运行时将提供更详细的错误信息,帮助开发者更快地定位问题。
public class NPEExample {
public static void main(String[] args) {
String str = null;
try {
str.length();
} catch (NullPointerException e) {
// 将显示更详细的错误信息
e.printStackTrace();
}
}
}
// 输出将类似于:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
4. Records(预览)
JDK 14 引入了一个新的 Java 类型:Records。这是一种特殊的类,旨在简化数据类的创建。
不能实例化,内部只能存在静态变量。
public record Info(int a, int b) {
private static int c;
}
public record Person(String name, int age) {
}
public class RecordExample {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
System.out.println(person.name());
System.out.println(person.age());
}
}
5. instanceof 进一步优化(预览)
public class PatternMatchingExample {
public static void main(String[] args) {
Object obj = "Hello, World!";
if (obj instanceof String str) {
System.out.println(str.length()); // 自动进行类型转换
}
}
}
6. 新的封装 JDK 类的方法
JDK 14 引入了一个新的 JDK 内部类封装工具 jdk.internal.vm.annotation.Hidden
。这一特性主要用于 JVM 内部的代码封装,帮助开发者更好地控制类的可见性和行为。
7. G1 优化
JDK 14 对 G1 垃圾回收器进行了增强,使其支持基于 NUMA(非统一内存访问)的内存分配。这项改进提高了在多处理器系统上的性能表现,优化了内存访问延迟。
# 使用 NUMA 感知内存分配运行应用
java -XX:+UseG1GC -XX:+UseNUMA -jar myapp.jar
8. ZGC 增强
JDK 14 将 ZGC(Z Garbage Collector)扩展到了 macOS 和 Windows 平台。
# 在 macOS 或 Windows 上使用 ZGC
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar myapp.jar
9. 废弃 CMS 垃圾回收器
JDK 14 正式把 CMS 标记为废弃的。
# 使用 G1 垃圾回收器替代 CMS
java -XX:+UseG1GC -jar myapp.jar
JDK15 新特性
JDK 15 于 2020 年 9 月发布,是一个短期支持版本(非 LTS)。
1. 隐藏类(Hidden Classes)
JDK 15 引入了隐藏类,这些类在运行时动态生成,仅供框架和库使用,不会在其他地方直接引用。隐藏类在 JVM 中是无法通过常规方法访问的,它们不会出现在正常的类路径上。这一特性提高了框架和库的灵活性和安全性,避免了命名冲突和意外访问。
import java.lang.invoke.*;
public class HiddenClassExample {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> hiddenClass = lookup.defineHiddenClass(
"public class Hello { public String hello() { return \"Hello, Hidden Class!\"; }}".getBytes(), true).lookupClass();
Object instance = hiddenClass.getConstructor().newInstance();
MethodHandle handle = lookup.findVirtual(hiddenClass, "hello", MethodType.methodType(String.class));
String result = (String) handle.invoke(instance);
System.out.println(result); // 输出: Hello, Hidden Class!
}
}
2. Text Blocks 正式发布
Text Blocks 在 JDK 13 和 JDK 14 中作为预览特性存在,在 JDK 15 中正式发布。它们允许多行字符串文字的简洁表示,提高了代码的可读性和可维护性。
public class TextBlockExample {
public static void main(String[] args) {
String jsonString = """
{
"name": "John",
"age": 30,
"city": "New York"
}
""";
System.out.println(jsonString);
}
}
3. Sealed Classes(预览)
JDK 15 引入了 Sealed Classes 作为预览特性,允许开发者通过 permits
关键字限制继承或实现某个类的子类或接口。Sealed Classes 提供了更细粒度的访问控制,增强了类层次结构的安全性。
public sealed class Shape permits Circle, Square {}
final class Circle extends Shape {
double radius;
}
final class Square extends Shape {
double side;
}
4. Records(第二次预览)
JDK 14 引入了 Records 作为预览特性,JDK 15 中对其进行了进一步改进。这种新型的数据类可以简化数据携带类的定义,自动生成常见的方法如 equals()
、hashCode()
和 toString()
。
public record Person(String name, int age) {}
public class RecordExample {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
System.out.println(person.name());
System.out.println(person.age());
}
}
5. ZGC 的改进
JDK 15 对 ZGC(Z Garbage Collector)进行了多项改进,使其支持类卸载(Class Unloading),提升了垃圾回收效率。
# 使用 ZGC 启动 Java 应用
java -XX:+UseZGC -XX:+ClassUnloadingWithConcurrentMark -jar myapp.jar
6. Shenandoah 垃圾回收器的改进
JDK 15 对 Shenandoah 进行了优化,使得 Shenandoah 的性能更好,内存占用更低。
7. EdDSA 签名算法
EdDSA Edwards-Curve Digital Signature Algorithm
JDK 15 增加了对 EdDSA 的支持,EdDSA 适用于需要高性能和强安全性的场景,如加密通信和数据签名。
import java.security.*;
import java.util.Base64;
public class EdDSAExample {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("Ed25519");
KeyPair keyPair = keyGen.generateKeyPair();
Signature sig = Signature.getInstance("Ed25519");
sig.initSign(keyPair.getPrivate());
sig.update("Hello, World!".getBytes());
byte[] signature = sig.sign();
System.out.println(Base64.getEncoder().encodeToString(signature)); // 打印签名
}
}
8. 外部内存访问 API(第二次孵化)
JDK 15 进一步完善了外部内存访问 API,使开发者能够更高效地访问非堆内存,这对于需要直接操作大数据或与原生库交互的应用非常有用。
import jdk.incubator.foreign.*;
public class ForeignMemoryAccessExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAccess.setByteAtOffset(segment, 0, (byte) 10);
byte value = MemoryAccess.getByteAtOffset(segment, 0);
System.out.println("Value: " + value); // 输出: Value: 10
}
}
}
JDK16
JDK 16 于 2021 年 3 月发布,是一个非长期支持版本(非 LTS)。
1. Records(正式发布)
在 JDK 14 和 JDK 15 中作为预览特性存在的 Records
,在 JDK 16 中正式发布。自动生成常用方法如 equals()
、hashCode()
和 toString()
,极大地减少了样板代码的编写。
public record Person(String name, int age) {}
public class RecordExample {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
System.out.println(person.name());
System.out.println(person.age());
System.out.println(person); // 自动生成的 toString 方法
}
}
2. instanceof
增强(正式发布)
在 JDK 14 和 JDK 15 中作为预览特性存在的模式匹配 instanceof
在 JDK 16 中得以正式发布。它简化了类型检查和转换的代码,使代码更加简洁易读。
public class PatternMatchingExample {
public static void main(String[] args) {
Object obj = "Hello, World!";
if (obj instanceof String str) {
System.out.println(str.length()); // 自动进行类型转换
}
}
}
3. jdk.incubator.foreign
包(直接内存访问 API 第二次孵化)
JDK 16 对外部内存访问 API 进行了进一步的改进,增强了开发者对非堆内存的操作能力。这对于需要与原生库交互或操作大数据的应用非常有用。
import jdk.incubator.foreign.*;
public class ForeignMemoryAccessExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAccess.setByteAtOffset(segment, 0, (byte) 10);
byte value = MemoryAccess.getByteAtOffset(segment, 0);
System.out.println("Value: " + value); // 输出: Value: 10
}
}
}
4. 向量 API jdk.incubator.vector
包(第一次孵化)
JDK 16 引入了新的 Vector API,允许开发者利用现代 CPU 的 SIMD 指令来编写高性能的向量运算代码。Vector API 使得开发者能够编写出高效的并行算法,从而提升应用的性能。
SIMD 单指令多条数据处理。
import jdk.incubator.vector.*;
public class VectorExample {
public static void main(String[] args) {
var species = FloatVector.SPECIES_256;
var a = FloatVector.fromArray(species, new float[] {1, 2, 3, 4, 5, 6, 7, 8}, 0);
var b = FloatVector.fromArray(species, new float[] {8, 7, 6, 5, 4, 3, 2, 1}, 0);
var c = a.add(b);
float[] result = new float[species.length()];
c.intoArray(result, 0);
System.out.println(Arrays.toString(result)); // 输出: [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
}
}
5. Unix-Domain Socket Channels
JDK 16 新增了 Unix-Domain Socket 通道支持,通过 java.nio.channels
包中的 SocketChannel
和 ServerSocketChannel
,开发者可以更方便地使用 Unix-Domain Sockets 实现本地进程间通信(IPC)。
import java.net.*;
import java.nio.channels.*;
import java.nio.ByteBuffer;
public class UnixDomainSocketExample {
public static void main(String[] args) throws Exception {
Path socketFile = Path.of("/tmp/mysocket");
try (ServerSocketChannel server = ServerSocketChannel.open(StandardProtocolFamily.UNIX)
.bind(new UnixDomainSocketAddress(socketFile));
SocketChannel client = SocketChannel.open(StandardProtocolFamily.UNIX)
.connect(new UnixDomainSocketAddress(socketFile))) {
ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.put("Hello, Unix-Domain Socket!".getBytes());
buffer.flip();
client.write(buffer);
}
}
}
6. G1 继续增强
JDK 16 对 G1 垃圾回收器的 NUMA 感知内存分配进行了优化,进一步提升了多处理器系统上的性能表现。
# 使用 NUMA 感知内存分配运行应用
java -XX:+UseG1GC -XX:+UseNUMA -jar myapp.jar
7. 移除了并发标记清除(CMS)垃圾回收器
在 JDK 14 中被标记弃用的 CMS 垃圾回收器在 JDK 16 中被彻底移除。
# 使用 G1 垃圾回收器替代 CMS
java -XX:+UseG1GC -jar myapp.jar
9. 基于值的类发出警告(JEP 390: Warnings for Value-Based Classes)
原始类型的包装类 Integer、Double,其构造函数上都已经标记有 @Deprecated(since="9", forRemoval = true) 注解。后续建议使用Integer a = 10;或者Integer.valueOf()
since 表示从JDK9开始弃用,forRemoval = true 未来肯定会被移除。
真对这种,JDK16开始,编译期将会产生'Integer(int)' is deprecated and marked for removal 告警。