JDK9~17部分新特性浅学
文章目录
- JKD9新特性—模块发开发
- JKD10新特性—var局部变量推导
- JDK11新特性—`sheBang`脚本
- JDK14新特性—文本块
- JDK14新特性—instanceof增强
- JKD16新特性—record类
- JDK17新特性—sealed类
- JDK17新特性—switch增强
JKD9新特性—模块发开发
-
模块化开发允许开发者将代码和资源组织成独立的模块,这些模块可以更好地进行管理、测试和维护。模块化开发可以提高Java应用程序的可伸缩性、性能和安全性。
-
在JDK 9中,Java平台被重新组织为一组相互依赖的模块,每个模块都有自己的代码和资源。开发者可以使用关键字"module"来定义一个模块,并通过模块描述文件(module-info.java)指定模块的依赖关系和对外暴露的API。
-
当使用模块化开发时,需要在每个模块的根目录下创建一个名为
module-info.java
的文件作为模块描述文件。示例:module com.example.myapp { requires java.base; // 依赖于Java基础模块 requires com.example.mylibrary; // 依赖于自定义的库模块 requires transitive com.example.myframework; // 传递依赖于自定义的框架模块 exports com.example.myapp.api; // 对外暴露给其他模块的包 opens com.example.myapp.internal; // 开放包以便其他模块可以反射访问 uses com.example.myapp.spi.MyService; // 使用Service Provider接口 provides com.example.myapp.spi.MyService with com.example.myapp.internal.MyServiceImpl; // 提供Service Provider实现 }
-
com.example.myapp
是模块的名称。 -
requires
关键字指定了该模块所依赖的其他模块,其中java.base
是Java基础模块,com.example.mylibrary
是自定义的库模块,而transitive
关键字表示传递性依赖,com.example.myframework
是自定义的框架模块。 -
exports
关键字指定该模块对外暴露的包,其他模块可以访问该包中的公共类和接口。opens
关键字用于开放包,以便其他模块可以使用反射访问该包中的类。 -
uses
关键字表示使用一个Service Provider接口,而provides
关键字表示该模块提供了对应的Service Provider实现。
-
- 通过模块描述文件,可以明确定义模块的依赖关系、对外暴露的API、开放的包和使用的Service Provider等。可以更好地管理模块之间的关系和对外的可见性。
JKD10新特性—var局部变量推导
-
必须能推导出实际类型
-
只能用于局部变量
-
局部变量类型推断(Local Variable Type Inference):允许在声明局部变量时使用关键字"var"来进行类型推导,而无需显式地指定变量的类型。
-
局部变量类型推断的好处是可以简化代码,减少冗余的类型声明。注意,var只能用于局部变量,不能用于方法的参数、方法返回值、成员变量以及静态变量的声明。尽管使用var进行类型推导,实际上仍然会在编译时确定变量的具体类型,并且不能将var用于未初始化的变量。
-
示例:
var name = "John Doe"; var age = 25; var scores = new int[]{90, 85, 95}; System.out.println(name); System.out.println(age); System.out.println(Arrays.toString(scores));
- 使用"var"关键字声明三个局部变量:name、age和scores。编译器会根据变量的初始化值进行类型推断,name被推断为String类型,age被推断为int类型,scores被推断为int数组类型。
- 综述,局部变量类型推断是JDK 10中引入的一个方便的语法糖,可以简化代码,并提高可读性和可维护性。
JDK11新特性—sheBang
脚本
#!
符号叫做sheBang
,,音译“释伴”——解释伴随行#!/bin/bash
以此开头的文件,在执行时会实际调用/bin/bash
程序来执行- 使用
java --source 11 test.sh
执行非java文件或者./文件名
执行文件#!C:/env/jdk --source 11 public class TestA{ public static void main(string[] args){ //... } }
JDK14新特性—文本块
- 文本块(Text Blocks),也被称为多行字符串文本。这个特性旨在改善在Java中编写多行字符串的体验。
- 使用文本块,可以更直观地编写包含换行符和缩进的多行字符串,而无需使用转义字符或连接多个字符串。
- 文本块还支持在开头和结尾使用空白行,并且可以通过缩进来对齐文本块中的内容。如果要在文本块中插入实际的换行符或空白行,可以使用反斜杠(\)进行转义。
- 文本块在处理XML、JSON、SQL查询和其他需要大量文本输入的情况下特别有用,可以减少转义字符的使用,并提高代码的可读性和编写效率。
- 示例:
String message = """ Hello, This is a multi-line text block. """;
- 使用三个双引号(“”")将字符串括起来,形成一个文本块。文本块中的换行符和缩进会被保留在字符串中,使其更易读和维护。
- 注意:文本块特性在JDK 14中为预览功能,并且需要在编译时使用"–enable-preview"选项进行启用。
- 总的来说,文本块是JDK 14中引入的一个方便的特性,使多行字符串的编写更加直观和简洁。
JDK14新特性—instanceof增强
- 增强的instanceof操作符特性,用于简化类型检查和类型转换的代码。
- 在JDK 14之前,当需要检查一个对象是否属于某个特定类型时,通常使用
instanceof
操作符。例如:if (obj instanceof String) { String str = (String) obj; // 执行针对String类型的操作 }
- 在例子中,首先使用instanceof操作符检查obj是否是String类型的实例,然后进行相应的类型转换。
- 而在JDK 14中,通过使用
instanceof
的模式匹配形式,直接将检查和类型转换合并到一行代码中,如下所示://instanceof操作符的结果被同时赋值给了一个新的变量str,并且只有在obj是String类型的实例时,才会进入到if语句的代码块中 if (obj instanceof String str) { // 执行针对String类型的操作 }
- 增强的instanceof操作符特性使得类型检查和类型转换更加简洁和方便,减少了冗余的代码。
- 注意:这个特性只能在局部变量中使用,并且在if语句的条件中执行类型检查和类型转换。
- 总的来说,JDK 14中的增强instanceof操作符特性提供了一种更简洁的方式来进行类型检查和类型转换,提高了代码的可读性和编写效率。
JKD16新特性—record类
-
record类是一种特殊的类,旨在提供一种更简洁、更易用的方式来定义不可变的数据类。
-
使用record类,可以在一行代码中定义一个包含属性、构造函数和其他方法的数据类。
-
示例:
record Point(int x, int y) { // 可以在这里定义其他方法 }
- 定义一个名为Point的record类,它有两个属性:x和y。这个record类自动提供一个构造函数,以及用于访问属性的方法。我们可以像使用普通类一样创建Point对象,并使用点号操作符访问它的属性。
-
与传统的Java类相比,record类还提供了一些额外的功能。它自动实现了equals()、hashCode()和toString()等方法,这些方法遵循一定的约定,使得我们无需手动编写这些通用方法。
-
另外,record类还支持解构(destructuring),这意味着可以使用解构声明将record对象的属性分解为局部变量。例如:
Point p = new Point(3, 5); int x = p.x(); int y = p.y();
-
通过解构声明,可以将Point对象的属性分别赋值给x和y变量。
-
record类的引入简化定义不可变数据类的过程,减少样板代码的编写,并提供了更好的可读性和易用性。
-
注意,record类是不可变的,即一旦创建了对象,就不能修改其属性值。
- 总的来说,JDK 16中的record类是一种用于定义不可变数据类的简洁方式,它提供了自动实现的常见方法,以及支持解构和不可变性。这个特性可以提高代码的可读性和编写效率。
JDK17新特性—sealed类
- 痛点:类的继承很难管理,使用sealed来显示管理
- 父类如果是sealed类,则必须至少有一个子类
- sealed类的子类,必须是final,sealed,non-sealed之一
-
sealed类是一种用于限制继承关系的类,它可以明确指定哪些类可以作为其子类。
-
通过使用sealed关键字修饰类或接口,可以限制继承该类或实现该接口的子类的范围。
-
示例:
public sealed class Shape permits Circle, Rectangle, Triangle { // 类的定义 } final class Circle extends Shape { // Circle类的定义 } final class Rectangle extends Shape { // Rectangle类的定义 } final class Triangle extends Shape { // Triangle类的定义 }
- 在示例中,定义一个sealed类Shape,并使用permits关键字指定了可以继承Shape的子类,包括Circle、Rectangle和Triangle。只有这三个类可以作为Shape的直接子类。
-
sealed类的引入可以提供更加严格的继承关系控制,使得类的继承结构更加清晰和可控。增加代码的可读性,防止类被滥用或不合理的继承。
-
注意:sealed类可以是final的,即不允许进一步派生其他子类。同时,sealed类的子类必须显示地声明自己的继承关系,即使用关键字extends或implements明确指定所继承的父类或实现的接口。
-
总的来说,JDK 17中的sealed类是一种限制继承关系的类,通过permits关键字明确指定允许的子类范围。这个特性可以提高继承关系的可控性和可读性,减少潜在的错误和滥用。
JDK17新特性—switch增强
-
增强的switch语句:旨在提供更灵活和易读的方式来编写复杂的分支逻辑。
-
在传统的switch语句中,每个case分支只能匹配一个常量值。而在增强的switch中,我们可以在case分支中使用表达式。
-
以下是一个使用增强的switch语句的示例:
int dayOfWeek = 3; String dayType = switch (dayOfWeek) { case 1, 2, 3, 4, 5 -> { yield "Weekday"; } case 6, 7 -> { yield "Weekend"; } default -> throw new IllegalArgumentException("Invalid day of week"); };
- 在示例中,使用增强的switch语句根据给定的dayOfWeek值来判断是工作日(Weekday)还是周末(Weekend)。在case分支中,我们使用逗号分隔的多个常量值进行匹配,并使用箭头(->)指定相应的结果。另外,增强的switch语句还引入一个新的关键字,即yield。它用于返回switch表达式的结果。
-
增强的switch语句还支持新的模式匹配功能,可以直接在case分支中使用类型模式匹配。
Object obj = "Hello"; int length = switch (obj) { case String s -> s.length(); case List list && !list.isEmpty() -> list.size(); default -> -1; };
-
增强的switch语句提供了更灵活和易读的方式来编写分支逻辑,使得代码看起来更简洁和直观。它可以减少冗余的代码,并提高代码的可读性和维护性。
-
总的来说,JDK 17中的增强的switch语句提供更多的功能和灵活性,包括表达式匹配、模式匹配和yield关键字。这个特性可以改善分支逻辑的编写方式,减少冗余代码,并提高可读性和可维护性。