Java新版本的重要语言特性(9-17)

news/2024/4/25 17:15:52

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 = """SELECTname,age,phone,wechatFROMcsdn_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 { }  //研究生

可以限制类的层次结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.tangninghui.cn.cn/item-72.htm

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 1149.文章浏览2

数据准备 drop table Views; Create table If Not Exists Views (article_id int, author_id int, viewer_id int, view_date date); Truncate table Views; insert into Views (article_id, author_id, viewer_id, view_date) values (1, 3, 5, 2019-08-01); insert into Vie…

不同场景下的JMETER设置

不同场景下的JMETER设置 1.基准测试 验证主要业务在单用户运行下的性能指标&#xff0c;为多用户并发并发和混合场景的性能分析提供基础参考。 基准测试JMETER线程组设置(在1秒内执行5个线程循环一次)&#xff1a; 2.并发测试 多用户在同一时间访问某一个模块或则应用的场景&…

亚马逊关于在澳大利亚销售儿童玩具和游戏的政策合规标准是什么?

亚马逊关于在澳大利亚销售儿童玩具和游戏的政策 在亚马逊澳大利亚商城中&#xff0c;设计用于或明确表示专供 14 岁及以下儿童玩耍用的所有商品或材料均视为儿童玩具。 商品根据以下标准确定为“儿童商品”&#xff1a; 预期用途&#xff1a; ASIN 是否可供儿童使用&#xff…

Linux下运行Jmeter压测

一、在Linux服务器先安装SDK 1、先从官网下载jdk1.8.0_131.tar.gz&#xff0c;再从本地上传到Linux服务器 2、解压&#xff1a;tar -xzf jdk1.8.0_131.tar.gz&#xff0c;生成文件夹 jdk1.8.0_131 3、在/usr/目录下创建java文件夹&#xff0c;再将 jdk1.8.0_131目录移动到/u…

LeetCode147之对链表进行插入排序(相关话题:链表)

题目描述 给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列…