JDK9
允许在接口中使用私有方法
JDK10
局部变量类型推断
var list = new ArrayList<String>();
- 声明时必须初始化
可以使用在:
- 具有初始化器的局部变量
- 增强型 for 循环中的索引变量
- 传统 for 循环中声明的局部变量
不能使用在:
- 推断方法的参数类型
- 构造函数参数类型推断
- 推断方法返回类型
- 字段类型推断
- 捕获表达式(或任何其他类型的变量声明)
建议:为了程序的易读性和可维护性,尽量显式定义变量类型。
JDK11
用于 Lambda 参数的局部变量语法
将局部变量和 Lambda 表达式的用法进行了统一,并且可以将注释应用于局部变量和 Lambda 表达式
@Nonnull var x = new Foo();
(@Nonnull var x, @Nullable var y) -> x.process(y)
- @NonNull 注解可以标注在方法、字段、参数之上,表示对应的值不能为空;
- @Nullable 注解可以标注在方法、字段、参数之上,表示对应的值可以为空;
JDK12
JDK13
JDK14
Switch 表达式
旧版:
- 一般使用冒号 :来作为语句分支代码的开始。
- 在每个分支结束之前,需要加上 break 关键字进行分支跳出,以防 switch 语句一直往后执行到整个 switch 语句结束。
新版:
- 提供了新的分支切换方式,即 -> 符号右则表达式方法体。
- 在执行完分支方法之后,自动结束 switch 分支。
- -> 右则方法块中可以是表达式、代码块或者是手动抛出的异常。
//旧版:
int dayOfWeek;
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
dayOfWeek = 5;
break;
case SATURDAY:
dayOfWeek = 6;
break;
case SUNDAY:
dayOfWeek = 7;
break;
default:
dayOfWeek = 0;
break;
}
//新版:
int dayOfWeek = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> 5;
case SATURDAY -> 6;
case SUNDAY -> 7;
default -> 0;
};
注意:
- 之前需要用变量来接收返回值,现在直接返回需要返回的结果。
- 不再需要显式地跳出当前分支,表达式执行完后会自动跳出,不会继续往后执行。
- 对于多个相同的 case 方法块,可以将 case 条件并列,不再通过每个 case 后面故意不加 break 关键字来使用相同方法块。
JDK15
文本块
文本块就是以三个引号开始,并以三个引号结束的字符串字面量。
文本块减少了转义,大大提高了代码可读性,尤其是代码中对SQL、HTML、JSON字符串进行拼接的情况。
// 旧版
String sqlTemplate = "SELECT\n" +
" name,\n" +
" age,\n" +
" phone,\n" +
" wechat\n" +
"FROM\n" +
" csdn_user;";
// 新版
String sqlTemplate = """
SELECT
name,
age,
phone,
wechat
FROM
csdn_user;
""";
JDK16
instanceof 模式匹配
对 instanceof 的改进,主要目的是为了让创建对象更简单、简洁和高效,并且可读性更强、提高安全性。
// 旧版
// 每次在检查类型之后,都需要强制进行类型转换。
// 类型转换后,需要提前创建一个局部变量来接收转换后的结果,代码显得多余且繁琐。
if (person instanceof Student) {
Student student = (Student) person;
student.say();
// other student operations
} else if (person instanceof Teacher) {
Teacher teacher = (Teacher) person;
teacher.say();
// other teacher operations
}
// 新版
// 对 person 对象进行类型匹配,校验 person 对象是否为 Student 类型
// 如果类型匹配成功,则会转换为 Student 类型,并赋值给模式局部变量 student
if (person instanceof Student student) {
//这里的 student 变量只能在 if 块中使用,而不能在 else if/else 中使用
student.say();
// other student operations
} else if (person instanceof Teacher teacher) {
teacher.say();
// other teacher operations
}
如果 if 条件中有 && 运算符时,当 instanceof 类型匹配成功,模式局部变量的作用范围也可以相应延长,如下面代码:
if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}
注意:这种作用范围延长,并不适用于或 || 运算符,因为即便 || 运算符左边的 instanceof 类型匹配没有成功也不会造成短路,依旧会执行到||运算符右边的表达式.但是如果左边instanceof 类型匹配没有成功,局部变量并未定义赋值,此时使用会产生问题。
Records类型
- Record 类型允许在代码中使用紧凑的语法形式来声明类,而这些类能够作为不可变数据类型的封装持有者。Record 这一特性主要用在特定领域的类上;
- 与枚举类型一样,Record 类型是一种受限形式的类型,主要用于存储、保存数据,并且没有其它额外自定义行为的场景下。
- 效果有些类似 Lombok 的 @Data 注解、Kotlin 中的 data class,但是又不尽完全相同,它们的共同点都是类的部分或者全部可以直接在类头中定义、描述,并且这个类只用于存储数据而已。
// 示例
public record Person(String name, int age) {
public static String address;
public String getName() {
return name;
}
}
// 编译后反编译的结果
public final class Person extends java.lang.Record {
private final java.lang.String name;
private final java.lang.String age;
public Person(java.lang.String name, java.lang.String age) { /* compiled code */ }
public java.lang.String getName() { /* 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 java.lang.String age() { /* compiled code */ }
}
可以得出,当用 Record 来声明一个类时,该类将自动拥有下面特征:
- 拥有一个构造方法
- 获取成员属性值的方法:name()、age()
- hashCode() 方法和 euqals() 方法
- toString() 方法类
- 对象被 final 关键字修饰,不能被继承;类的成员变量也都被 final 修饰,不能再被赋值使用。
- 可以在 Record 声明的类中定义静态属性和方法。
- 注意,不能在 Record 声明的类中定义成员变量,类也不能声明为抽象类等。
JDK17
密封的类和接口
用来增强 Java 编程语言,防止其他类或接口扩展或实现它们。
使用修饰符sealed,您可以将一个类声明为密封类。
密封的类使用关键字permits列出可以直接扩展它的类。
子类可以是最终的、非密封的或密封的。
继承了密封类的子类可以使用non-sealed修饰,这样任何类都可以继承这个子类。
// 旧版
public class Person { } //人
class Teacher extends Person { }//教师
class Worker extends Person { } //工人
class Student extends Person{ } //学生
// 新版
// 添加sealed修饰符,permits后面跟上只能被继承的子类名称
public sealed class Person permits Teacher, Worker, Student{ } //人
// 子类可以被修饰为 final
final class Teacher extends Person { }//教师
// 子类可以被修饰为 non-sealed,此时 Worker类就成了普通类,谁都可以继承它
non-sealed class Worker extends Person { } //工人
// 任何类都可以继承Worker
class AnyClass extends Worker{}
//子类可以被修饰为 sealed,同上
sealed class Student extends Person permits MiddleSchoolStudent,GraduateStudent{ } //学生
final class MiddleSchoolStudent extends Student { } //中学生
final class GraduateStudent extends Student { } //研究生
可以限制类的层次结构。
本文含有隐藏内容,请 开通VIP 后查看