8. JDK15 新特性
参考网站: openjdk.org/projects/jd…
makefile复制代码
339:
Edwards-Curve Digital Signature Algorithm (EdDSA)曲线数字签名算法
360:
Sealed Classes (Preview)密封类(预览)
371:
Hidden Classes隐藏类别
372:
Remove the Nashorn JavaScript Engine删除 Nashorn JavaScript 引擎
373:
Reimplement the Legacy DatagramSocket API重新实现遗留 DatagramSocket API
374:
Disable and Deprecate Biased Locking禁用和取消偏差锁定
375:
Pattern Matching for instanceof (Second Preview)模式匹配(第二次预览)
377:
ZGC: A Scalable Low-Latency Garbage CollectorZGC: 一个可伸缩的低延迟垃圾收集器
378:
Text Blocks文本块
379:
Shenandoah: A Low-Pause-Time Garbage CollectorShenandoah: 一个低暂停时间的垃圾收集器
381:
Remove the Solaris and SPARC Ports删除 Solaris 和 SPARC 端口
383:
Foreign-Memory Access API (Second Incubator)外部内存访问 API (第二个孵化器)
384:
Records (Second Preview)纪录(第二次预览)
385:
Deprecate RMI Activation for Removal不推荐激活 RMI 以便删除
8.1 Sealed Classes(密封类)
密封类(Sealed Classes)是JDK 15引入的一项重要特性,它是一种新的类和接口修饰符,用于控制类的继承关系。通过将类或接口声明为密封类,可以限制哪些类可以继承或实现该密封类 密封类的主要目的是提供更严格的访问控制,以确保继承层次结构的完整性和安全性。在使用密封类时,开发者可以明确指定允许继承的类的范围,这样可以防止不受控制的扩展和继承。 要将一个类声明为密封类,需要使用sealed
关键字进行修饰。例如:
sealed class Shape permits Circle, Square, Triangle {
// Class body
}
在上面的例子中,Shape
是一个密封类,它允许继承的类有Circle
、Square
和Triangle
。这意味着只有这三个类可以直接继承Shape
,其他类无法继承它。如果其他类尝试继承Shape
,编译器将报错。 通过使用密封类,可以有效地控制继承关系,并减少意外的扩展。这对于框架和库的设计非常有用,可以确保只有受信任的类可以扩展或实现密封类。 此外,密封类与模式匹配(Pattern Matching)功能相结合,可以更方便地处理密封类的实例。模式匹配可以根据实例的类型进行匹配,并根据匹配的结果执行相应的操作,从而简化了类型检查和转换的代码。 总之,密封类是JDK 15引入的一项重要特性,它通过控制继承关系来提供更严格的访问控制和安全性。它可以帮助开发者更好地设计类层次结构,并减少意外的扩展。
8.2 Text Blocks(文本块)
文本块(Text Blocks)是JDK 15引入的一项重要特性,它提供了一种更自然、更易读的多行字符串表示形式,以减少在代码中编写长字符串时的转义字符和格式化问题。
在传统的Java中,如果要编写一个包含多行文本的字符串,需要使用转义字符(例如\n
)或连接操作符(+
)将多行字符串拼接在一起。这样的写法不仅冗长而且难以阅读和维护。
使用文本块,可以更简洁地表示多行字符串,而无需使用转义字符或连接操作符。文本块使用三个引号(""")将多行字符串包裹起来,并通过缩进来定义字符串的内容。例如:
String textBlock = """
Hello,
This is a multi-line
text block.
""";
在上面的例子中,textBlock
是一个文本块,包含了三行文本。通过使用文本块,我们可以直观地看到字符串的格式和结构,而无需担心转义字符和格式化问题。 文本块还支持一些额外的特性,例如去除前导空格和尾随空格。可以使用~
字符来指定文本块的缩进级别,从而控制文本块中的空格。
String indentedBlock = """
This is an indented block
with leading and trailing spaces.
""".stripIndent();
在上面的例子中,stripIndent()
方法会自动去除前导空格,生成一个不包含缩进的文本块。 文本块在许多场景中都非常有用,特别是在编写HTML、JSON、SQL或其他格式化字符串时。它提供了更清晰和易于维护的代码,提高了开发效率。 需要注意的是,文本块是在编译时进行处理的,并不会在运行时影响字符串对象的表示方式。因此,文本块并不改变字符串的基本性质和操作。
8.3 Hidden Classes(隐藏类)
隐藏类(Hidden Classes)是JDK 15引入的一项特性,它允许在运行时动态生成类,同时不会对程序的性能产生负面影响。隐藏类对于某些特定的应用场景非常有用,如动态代理、代码生成和Java虚拟机的实现。 隐藏类的主要目的是在不暴露类的字节码的情况下,允许生成和使用类。这对于一些涉及敏感逻辑或需要动态生成和加载类的应用程序非常有用。 隐藏类的生成和使用是通过Java虚拟机的Lookup
对象和MethodHandles
API进行的。Lookup
对象提供了对类的私有成员访问的权限,并可以用于创建隐藏类。MethodHandles
API提供了对方法句柄的操作和调用。 生成隐藏类的过程可以概括为以下几个步骤:
- 获取
Lookup
对象:通过反射或其他方式获取Lookup
对象,该对象具有足够的权限来创建隐藏类。 - 定义类的结构:使用
Lookup
对象的defineHiddenClass()
方法定义类的结构,包括类的名称、父类、接口等。 - 加载和链接类:使用
Lookup
对象的lookupClass()
方法加载和链接隐藏类。 - 创建实例和调用方法:使用
MethodHandles
API和隐藏类的句柄来创建实例和调用方法。
隐藏类的主要优势在于,它们可以在运行时动态生成和加载,而无需事先编写和编译类的字节码。这对于某些场景,如实现动态代理、插件系统、代码生成和热部署等,提供了更大的灵活性和扩展性。 需要注意的是,隐藏类是一项高级特性,通常在特定的应用程序框架和库中使用,而不是普通的应用程序开发中。使用隐藏类需要谨慎,确保了解其工作原理和适用场景。
8.4 Records(记录类)
JDK 15对记录类进行了一些改进,主要包括:
- 扩展性构造函数(Extended Constructor):在JDK 15之前,记录类只有一个隐式的构造函数,它接受所有属性作为参数。在JDK 15中,记录类引入了扩展性构造函数,允许开发者自定义构造函数,同时保留隐式构造函数的功能。
- @Override支持:在JDK 15之前,由于记录类的方法是由编译器自动生成的,因此无法使用@Override注解来标记覆盖父类方法。在JDK 15中,支持在记录类方法上使用@Override注解,以便更好地表示其覆盖关系。
8.5 Pattern Matching for instanceof(instanceof的模式匹配)
JDK 15引入了一项重要的特性,即"Pattern Matching for instanceof"(instanceof的模式匹配)。这个特性通过简化对类型的检查和转换来提高代码的可读性和简洁性。 在Java中,我们通常使用instanceof
运算符来检查对象是否属于某个特定类型。在JDK 15之前,这通常需要将检查通过后的对象强制转换为目标类型,以便在后续的代码中使用。这样的代码模式非常普遍。 而在JDK 15中,引入了模式匹配的功能,可以将instanceof
与类型转换结合起来,以更简洁的方式完成类型检查和转换。下面是一个使用模式匹配的示例:
if (obj instanceof String str) {
System.out.println(str.length());
}
在上面的例子中,我们使用instanceof
运算符检查obj
是否是String
类型。如果是,那么我们可以在条件块内部直接使用str
作为String
类型的对象,并且编译器会自动将其视为String
类型。这样,我们就可以直接调用str
上的方法或访问其属性,而无需进行额外的强制类型转换。 这种模式匹配的语法可以帮助开发者更直接地处理类型检查和类型转换,并减少了样板代码的编写。它提供了更简洁和易读的方式来处理复杂的类型判断和转换逻辑。 需要注意的是,模式匹配的作用域仅限于条件块内部,超出该范围后,变量将不再被视为特定类型。