[Java]JDK新特性

news/2024/7/24 14:52:22/

目录

一、JDK新特性

1.1Java Record

1.1.1Record的使用

1.1.2Instance Methods

1.1.3静态方法 Static Method

1.1.4Record构造方法

1.1.5Record与Lombok

1.1.6Record实现接口

1.1.7Local Record

1.1.8嵌套Record

1.1.9instanceof判断Record类型

1.1.10总结

1.2Switch

1.2.1箭头表达式

1.2.2yield返回值

1.2.3Java Record

1.3Text Block

1.3.1认识文本块

1.3.2字符串比较与方法

1.3.3空白

1.3.4文本块的方法

1.3.5转义字符

1.3.6总结

1.4var

1.4.1var声明局部变量

1.4.2什么时候使用var

1.5sealed

1.5.1Sealed Classes

1.5.2Sealed Interface


一、JDK新特性

  • JDK8-19新增了不少新特性,这里我们把实际常用的新特性进行介绍。

    • Java Record

    • Switch 开关表达式

    • Text Block 文本块

    • var 声明局部变量

    • sealed 密封类

1.1Java Record

  • Java14中预览的新特性叫做Record,在Java中,Record是一种特殊类型的Java类。可用来创建不可变类,语法简短。

  • 任何时候创建Java类,都会创建大量的样板代码,如:

    • 每个字段的set、get方法

    • 公共的构造方法

    • 重写hashCode()、toString()、equals()方法

  • 使用Java Record避免上述的样板代码,如下特点:

    • 带有全部参数的构造方法

    • public访问器

    • toString()、hashCode()、equals()

    • 无set、get方法,没有遵循Bean的命名规范

    • final类,不能继承Record,Record为隐式的final类,除此之外与普通类一样

    • 不可变类,通过构造创建Record

    • final属性不可修改

    • 不能声明实例属性,能声明static成员

1.1.1Record的使用

  • IDEA新建Class,选择类Record

1.创建 Student Record

public record Student(Integer id, String name, String email, Integer age) {
}

2.创建 Record对象

@Test
public void test01() {//创建Record对象Student student = new Student(1001, "张三", "zhangsan@qq.com", 20);System.out.println(student);
​//public访问器获取属性值,只读,没有set、get方法Integer id = student.id();String name = student.name();System.out.println("id=" + id);System.out.println("name=" + name);
​Student student1 = new Student(1002, "李四", "lisi@qq.com", 21);System.out.println(student1);
​System.out.println("student1.equals(student)="+student1.equals(student));
​System.out.println(student1.name());System.out.println(student1.id());
}

 

3.查看控制台输出结果

 

  • Record 通过构造方法创建了只读对象,能够读取每个属性,不能设置新的属性值。

  • Record 用于创建不可变的对象,同时减少了样板代码。

  • Record 对每个属性提供了public访问器,例如student.name()

1.1.2Instance Methods

  • Record是Java类,和普通Java类一样定义方法。

1.创建实例方法

//实例方法,concat连接字符串
public String concat() {return String.format("姓名是%s,年龄是%d", this.name, this.age);
}

2.调用实例方法

@Test
public void test2() {Student student = new Student(1001, "张三", "zhangsan@qq.com", 20);//使用对象,调用实例方法System.out.println(student.concat());
}

1.1.3静态方法 Static Method

  • Record类定义静态方法,和普通类一样。

1.创建静态方法

//静态方法,把email转为大写
public static String emailToUpperCase(String email) {return Optional.ofNullable(email).orElse("no email").toUpperCase();
}

2.测试静态方法

@Test
public void test3() {//使用类,调用静态方法String email = Student.emailToUpperCase("zhangsan@qq.com");System.out.println(email);
}

1.1.4Record构造方法

  • 我们可以在Record中添加构造方法,有三种类型的构造方法:

    • 紧凑型构造方法:没有任何参数,甚至没有括号

    • 规范构造方法:以所有成员作为参数

    • 定制构造方法:自定义参数个数

1.紧凑和定制构造方法

//紧凑构造方法
public Student {System.out.println("id=" + id);if (id < 1000) {throw new RuntimeException("id<1000");}
}
​
//自定义构造方法
public Student(Integer id, String name) {this(id, name, null, null);
}

2.编译Student.java->Student.class

/*紧凑构造方法和规范构造方法合并了*/
public Student(Integer id, String name, String email, Integer age) {System.out.println("id=" + id);if (id < 1000) {throw new RuntimeException("id<1000");} else {this.id = id;this.name = name;this.email = email;this.age = age;}}
​public Student(Integer id, String name) {this(id, name, (String)null, (Integer)null);}

3.测试

@Test
public void test4() {Student student = new Student(1001, "张三");System.out.println(student);
}

1.1.5Record与Lombok

  • Java Record是创建不可变类且减少样板代码的好方法,Lombok是一种减少样板代码的工具。

  • Lombok提供语法的便利性,通常预装一些代码模板,根据您加入到类中的注解自动执行代码模板。这样的库纯粹是为了方便实现POJO类,通过预编译代码,将代码的模板加到class中。

  • Java Record是语言级别的,一种语义特性。为了建模而用,数据聚合。简单说就是提供了通用的数据类,充当“数据载体”,用于在类和应用程序之间进行数据传输。

1.1.6Record实现接口

  • Java Record可以与普通类一样实现接口,重写接口的方法。

1.创建新的接口,定义一个规范方法

public interface Print {void print();
}

2.创建新的Record实现接口,重写接口的方法,实现当前Record有关的业务逻辑

public record ProductRecord(Integer id, String name, Integer qty) implements Print {@Overridepublic void print() {StringJoiner joiner = new StringJoiner("-");String s = joiner.add(id.toString()).add(name).add(qty.toString()).toString();System.out.println("商品信息:" + s);}
}

3.测试print方法

@Test
public void test5() {ProductRecord productRecord = new ProductRecord(1001, "电脑", 1000);productRecord.print();
}

1.1.7Local Record

  • Record 可以作为局部对象使用,在代码块中定义并使用Record。

定义Local Record

@Test
public void test6() {//定义local recordrecord SaleRecord(String saleId, String productName, Double money) {}//创建对象SaleRecord saleRecord = new SaleRecord("001", "显示器", 3000.00);
​System.out.println("saleRecord=" + saleRecord);
}

1.1.8嵌套Record

  • 多个Record可以组合定义,一个Record能够包含其他得到Record。

1.定义Record

public record Address(String city,String address,String zipcode) {}
public record Phone(String areaCode,String number) {}
public record Customer(String id, String name, Address address, Phone phone) {}

2.创建Customer对象并测试

@Test
public void test7() {Address address = new Address("郑州", "新密", "452370");Phone phone = new Phone("0371", "60281234");Customer customer = new Customer("1001", "张三", address, phone);System.out.println(customer);System.out.println(customer.address().address());System.out.println(customer.phone().number());
}

1.1.9instanceof判断Record类型

  • instance能够与Java Record一起使用,编译器知道记录组件的确切数量和类型。

  • instanceof是Java的一个保留关键字,左边是对象,右边是类,返回类型是Boolean类型。

  • instanceof是测试左边的对象是否是右边类或者该类的子类创建的实例对象,是返回true,否返回false。

1.声明Person Record,拥有两个属性name和age

public record Person(String name, Integer age) {}

2.在一个业务方法判断当是Record类型时,继续判断age年龄是否满足18岁

public class SomeService {//定义业务方法,判断年龄是否18public boolean isEligible(Object obj) {/*if (obj instanceof Person(String name,Integer age)) {return age >= 18;}*/if (obj instanceof Person(String name,Integer age) p) {return p.age() >= 18;}return false;}
}

3.测试

@Test
public void test8() {Person person = new Person("李四", 20);SomeService someService = new SomeService();boolean flag = someService.isEligible(person);System.out.println(flag);
}

1.1.10总结

  • java.lang.Class类与Record类有关的两个方法

    • 判断一个类是否是Record类型:boolean isRecord()

    • Record的数组,表示此记录类的所有记录组件:RecordComponent[] getRecordComponents()

//判断Customer是否为Java Record类型
boolean record = customer.getClass().isRecord();
System.out.println("record=" + record);
​
RecordComponent[] recordComponents = customer.getClass().getRecordComponents();
for (RecordComponent recordComponent : recordComponents) {System.out.println("recordComponent=" + recordComponent);
}

1.2Switch

  • Switch特点:

    • 支持箭头表达式

    • 支持yield返回值

    • 支持Java Record

1.2.1箭头表达式

@Test
public void test01() {int week = 7;String memo = "";//表示计算结果switch (week) {case 1 -> memo = "星期日,休息";case 2, 3, 4, 5, 6 -> memo = "工作日";case 7 -> memo = "星期六,休息";default -> throw new RuntimeException("无效的日期");}System.out.println("memo=" + memo);
}

1.2.2yield返回值

  • yield让switch作为表达式,能够返回值。

  • 无需中间变量,switch作为表达式计算,可以得到结果,yield是表达式的返回值。

@Test
public void test02() {int week = 10;String memo = switch (week) {case 1:yield "周日";case 2, 3, 4, 5, 6:yield "工作日";case 7:yield "周六";default:yield "无效日期";};System.out.println("week = " + memo);
}
  • 多表达式,case与yield结合使用

@Testpublic void test03() {int week = 7;String memo = switch (week) {case 1 -> {System.out.println("周日,执行了代码块");yield "周日";}case 2, 3, 4, 5, 6 -> {System.out.println("工作日,执行了代码块");yield "工作日";}case 7 -> "周六";default -> {System.out.println("其它");throw new RuntimeException("无效日期");}};System.out.println("week=" + memo);}
  • 提示

    • case -> 不能与 case : 混用,一个switch语句块中使用一种语法格式。

1.2.3Java Record

  • switch表达式中使用record,结合case -> 表达式 ,yield实现复杂的计算。

1.准备三个Record

public record Line(int x, int y) {}
public record Circle(int r) {}
public record Rectangle(int width, int height) {}

2.switch record

@Test
public void test04() {Circle circle = new Circle(10);Line line = new Line(10, 20);Rectangle rectangle = new Rectangle(10, 20);
​Object obj = circle;int res = switch (obj) {case Circle(int r) -> {System.out.println("圆的半径为:" + r);yield 3 * r * r;}case Line(int x,int y) -> {System.out.println("线段的长度为:" + (y - x));yield y - x;}case Rectangle(int w,int h) -> w * h;default -> 0;};System.out.println("res=" + res);
}

1.3Text Block

  • Text Bolck处理多行文本十分方便,无需连接“+”单引号、换行符等。

1.3.1认识文本块

  • 语法:使用三个双引号括起来的字符串。

    """

    内容

    """

  • 例如:

    String name = """lisi"""; //Error 不能将文本块放在单行上
    String name= """lisi20"""; //Error 文本块的内容不能在没有中间行结束符的情况下跟随三个开头双引号
    String myname= """zhangsan20
    """; //正确
    String s1 = """张三""";//正确

1.3.2字符串比较与方法

  • 三个双引号字符""" 与两个双引号""的字符串处理是一样的,与普通字符串一样使用。例如 equals(),"==",连接字符串("+"),作为方法的参数等。

@Test
public void fun1() {String s1 = """lisi""";String s2 = """lisi""";//比较字符串boolean b1 = s1.equals(s2);System.out.println("b1 = " + b1);//使用 == 的比较boolean b2 = s1 == s2;System.out.println("b2 = " + b2);String msg = """hello world""";//字符串方法 substringString sub = msg.substring(0, 5);System.out.println("sub = " + sub);}

1.3.3空白

示例:

@Test
public void test02() {//按tab键向右移动,保留左侧空格String msg = """<html><body>张三</body></html>""";System.out.println(msg);
​String colors = """blueredgreen""";//indent(int space) 包含缩进,space为空格的数量colors = colors.indent(10);System.out.println(colors);
}

输出

1.3.4文本块的方法

  • Text Block的格式方法 formatted()

@Test
public void test03() {String info= """Name:%s\nPhone:%sAge:%d""".formatted("张三","123",23);System.out.println(info.translateEscapes().strip());
}

  • String strip():删除每行开头和结尾的空白

  • String translateEscapes():转义序列转换为字符串字面量

1.3.5转义字符

@Test
public void test04() {String str= """Spring Boot 是一个快速开发框架 \基于\"Spring\"框架,创建 Spring 应用 \内嵌 Web 服务器,以 jar 或 war 方式运行 \""";System.out.println(str);
}

1.3.6总结

  • 多行字符串,应该使用Text Block

  • 当Text Block可以提高代码的清晰的时,推荐使用。例如代码中嵌入SQL语句。

  • 避免不必要的缩进,开头和结尾部分。

  • 空格和制表符不能混合使用。

  • 对于大多数多行字符串, 分隔符位于上一行的右端,并将结束分隔符位于文本块单独行上。

1.4var

  • 在JDK10及更高版本中,可以使用var标识符声明具有非空初始化式的局部变量,这可以帮助您编写简洁的代码,消除冗余信息使代码更具有可读性,谨慎使用。

1.4.1var声明局部变量

  • var特点

    • var 是一个保留字,不是关键字(可以声明var为变量名)

    • 方法内声明的局部变量,必须有初始值,不能为空

    • 每次声明一个变量,不能复合声明多个变量。var s1="Hello", age=20; //Error

    • var 动态类型是编译器根据变量所赋的值来推断类型

    • var代替显示类型,代码简洁,减少不必要的排版

  • var优缺点

    • 代码简洁和整齐

    • 降低了程序的可读性

示例

//通常
try (Stream<Customer> result = dbconn.executeQuery(query)) {
//...
//推荐
try (var customers = dbconn.executeQuery(query)) {
//...
}
比较 Stream<Customer> result 与 var customers

1.4.2什么时候使用var

  • 简单的临时变量

  • 复杂,多步骤逻辑,嵌套的表达式等,简短的变量有助于理解代码

  • 能够确定变量的初始值

  • 变量类型比较长时

示例

public void fun1(){var s1="lisi";var age = 20;for(var i=0;i<10;i++){System.out.println("i = " + i);}List<String> strings = Arrays.asList("a", "b", "c");for (var str: strings){System.out.println("str = " + str);}

1.5sealed

  • Sealed Classes 主要特点是限制继承,Java中通过继承增强,扩展了类的能力,复用某些功能。当这种能力不受控,与原有类的设计相违背,导致不预见的异常逻辑。

  • Sealed 限制无限的扩张。

  • Java种已有的sealed的设计

    • final关键字,修饰类不能被继承

    • private限制私有类

  • sealed作为关键字可以在class和interface上使用,结合permits关键字。定义限制继承的密封类。

1.5.1Sealed Classes

sealed class 类名 permits 子类1,子类2,... 列表{}

1.声明sealed Class

public sealed class Shape permits Circle,Square,Rectangle{public void draw(){System.out.println("画一个Shape");}
}
  • permits表示允许的子类,一个或多个

2.声明子类

  • 子类声明的三种方式

    • final 终结,依然是密封的

    • sealed 子类是密封的,需要子类实现

    • non-sealed 非密封类,扩展使用,不受限

//第一种 final
public final class Circle extends Shape {
}
//第二种 sealed class
public sealed class Square extends Shape permits RoundSquare {@Overridepublic void draw() {System.out.println("=======Square 图形======");}
}
//密封类的子类的子类
public final class RoundSquare extends Square{
}
//非密封类 , 可以被扩展。放弃密封
public non-sealed class Rectangle extends Shape {
}
//继承非密封类
public class Line extends Rectangle{
}

1.5.2Sealed Interface

  • 密封接口同密封类

1.声明密封接口

public sealed interface SomeService permits SomeServiceImpl {void doSome();
}

2.实现接口

public final class SomeServiceImpl implements SomeService {@Overridepublic void doSome() {System.out.println("SomeServiceImpl");}
}


http://www.ppmy.cn/news/1016195.html

相关文章

【reactNative混合安卓开发~使用问题持续更】

reactNative混合安卓开发 reactNative开发移动端reactNative界面开发RN问题记录1、使用theme.js写的公共组件报错&#xff08;funcMap[props] undefined&#xff09; reactNative开发移动端 用reactNative&#xff08;VsCode编译器&#xff09;开发移动端界面&#xff0c;Andr…

SpringBoot整合达梦数据库

近期接到了一个需要国产化的项目&#xff0c;用到了达梦数据库&#xff0c;没想到一开始配置就出现了问题&#xff0c;下面把配置给大家粘贴出来&#xff0c;大家少踩点坑。 一、先下载达梦数据库 这是达梦数据库下载链接&#xff0c;达梦数据库没有免费的&#xff0c;个人好…

初识mysql数据库之引入mysql客户端库

目录 一、下载第三方库 1. 准备工作 1. 使用mysql官网提供的库 2. yum源安装 二、测试第三方库是否可用 三、mysql常用接口介绍 1. 查看官方文档 2. 初始化 3. 关闭mysql 4. 连接mysql 5. 下达sql指令 四、一个简单的C客户端库连接mysql程序 1. 头文件 2. 初始化…

Stable Diffuion webui Mac版本安装过程

系统环境 操作系统&#xff1a;MacOS Ventura13.5 芯片&#xff1a;Apple M2 Max Python: 3.10 安装前置准备 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git注意事项&#xff1a;修改源码内全部 git clone 链接&#xff0c;设置代理 https://ghpr…

Node.js新手在哪儿找小项目练手?

前言 可以参考一下下面的nodejs相关的项目&#xff0c;希望对你的学习有所帮助&#xff0c;废话少说&#xff0c;让我们直接进入正题>> 1、 NodeBB Star: 13.3k 一个基于Node.js的现代化社区论坛软件&#xff0c;具有快速、可扩展、易于使用和灵活的特点。它支持多种数…

代理设计模式——静态代理和动态代理

代理模式 在代理模式&#xff08;Proxy Pattern&#xff09;中&#xff0c;一个类代表另一个类的功能。这种类型的设计模式属于结构型模式&#xff0c;在代理模式中&#xff0c;我们创建具有现有对象的对象&#xff0c;以便向外界提供功能接口。 意图&#xff1a;为其他对象提…

无人车沿着指定线路自动驾驶与远程控制的实践应用

有了前面颜色识别跟踪的基础之后&#xff0c;我们就可以设定颜色路径&#xff0c;让无人车沿着指定线路做自动驾驶了&#xff0c;视频&#xff1a;PID控制无人车自动驾驶 有了前几章的知识铺垫&#xff0c;就比较简单了&#xff0c;也是属于颜色识别的一种应用&#xff0c;主要…

【基础类】—前后端通信类系统性学习

一、什么是同源策略及限制 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。源&#xff1a;协议、域名和端口&#xff0c; 默认端口是80 三者有一个不同&#xff0c;即源不同&#xff0c;就是跨域 ht…

LeetCode 30题:串联所有单词的子串

题目 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff0c; 那么 "…

linux下离线安装docker

linux下离线安装docker 一、安装docker Docker 官网离线安装文档 https://docs.docker.com/engine/install/binaries/ 整理步骤如下&#xff1a; 官网下载 docker 安装包&#xff0c;地址为 https://download.docker.com/linux/static/stable/&#xff0c;如果是x86就选择x…

face_recognition人脸识别与人脸检测

1、安装face_recognition库 pip install face_recognition face_recognition库的人脸识别是基于业内领先的C开源库dlib中的深度学习模型&#xff0c;安装face_recognition库的同时会一并安装dlib深度学习框架。 2、face_recognition库的使用 1&#xff09;load_image_file加…

账号登录相关的一点随笔

最后更新于2023年8月8日 14:25:32 JWT验证&#xff1a; 简单&#xff1a;一个token验证&#xff1b; 前端发来登录信息&#xff0c;后端验证通过后&#xff0c;将token发回前端&#xff1b; 复杂&#xff1a;Access Token Refresh Token验证&#xff1a; 将Access Token和R…

Python async 异步编程

同步&#xff1a;循序渐进执行操作&#xff08;遇到IO等待&#xff0c;CPU就真的等待IO结束继续执行&#xff09; 异步&#xff1a;是以IO非阻塞的方式进行计算或数据传输(利用一个任务IO等待的时间&#xff0c;去执行一些其他任务&#xff0c;无需等待)&#xff0c;以提高系统…

RN实现混合式开发-内嵌html

介绍 React Native WebView是一个用于在React Native应用中嵌入Web内容的组件。它允许你在应用中显示网页、加载HTML字符串、运行JavaScript代码等。 使用 首先&#xff0c;你需要在你的React Native项目中安装React Native WebView库。可以使用以下命令进行安装&#xff1a;…

折半查找、

描述 给定一个已按从大到小排序好的数组和一个数&#xff0c;使用折半查找算法&#xff0c;输出该数在数组中的位置。如果该数不在数组中&#xff0c;则输出“无此数”。 输入 输入为两行&#xff0c;第一行包含多个整数&#xff0c;用空格分隔&#xff0c;表示已排序好的数…

Transformer理论学习

Transformer出自于论文《attention is all you need》。 一些主流的序列模型主要依赖于复杂的循环结构或者CNN&#xff0c;这里面包含了编解码器等。而Transformer主要的结构是基于注意力机制&#xff0c;而且是用多头注意力机制去替换网络中的循环或者CNN(换言之就是transfor…

Unity之ShaderGraph 节点介绍 数学节点

数学 高级Absolute&#xff08;绝对值&#xff09;Exponential&#xff08;幂&#xff09;Length&#xff08;长度&#xff09;Log&#xff08;对数&#xff09;Modulo&#xff08;余数&#xff09;Negate&#xff08;相反数&#xff09;Normalize&#xff08;标准化矢量&…

Easys Excel的表格导入(读)导出(写)-----java

一,EasyExcel官网: 可以学习一些新知识: EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 二,为什么要使用easyexcle excel的一些优点和缺点 java解析excel的框架有很多 &#xff1a; poi jxl,存在问题&#xff1a;非常的消耗内存&#xff0c; easyexcel 我们…

前端项目打包报错JavaScript heap out of memory(js堆内存不足)

项目打包出现类似以下报错 <--- JS stacktrace --->FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory1: 00007FF646E9B1EF v8::internal::CodeObjectRegistry::~CodeObjectRegistry1235992: 00007FF646E28BA6 v8::internal::Microta…

车云一体化系统基础理论

车云一体化系统基础理论 介绍目标正文 参考文档 介绍 最近在调研车云链路一体化的整套解决方案&#xff0c;涉及分布式消息队列&#xff08;RocketMQ&#xff09;、分布式存储&#xff08;Doris&#xff09;、离线数据处理&#xff08;Spark&#xff09;、用户行为日志分析&am…