JDK有用的新特性-Java Record
Java Record
Java14 中预览的新特性叫做 Record,在 Java 中,Record 是一种特殊类型的 Java 类。可用来创建不可变类,语法
简短。参考JEP 395. Jackson 2.12 支持 Record 类
任何时候创建 Java 类,都会创建大量的样板代码,我们可能做如下:
- 每个字段的 set,get 方法
- 公共的构造方法
- 重写 hashCode, toString(), equals()方法
Java Record 避免上述的样板代码,如下特点:
- 带有全部参数的构造方法
- public 访问器
- toString(),hashCode(),equals()
- 无 set,get 方法。没有遵循 Bean 的命名规范
- final 类,不能继承 Record,Record 为隐士的 final 类。除此之外与普通类一样
- 不可变类,通过构造创建 Record
- final 属性,不可修改
- 不能声明实例属性,能声明 static 成员
Record使用
IDEA 新建 Class,选择类 Record
step1: 创建 Student Record
public record Student(Integer id,String name,String email,Integer age) {
}
step2:创建 Record 对象
public void test(String[] args) {
//创建Record对象
Student lisi = new Student(1001,"lisi","lisi@qq.com",20);
System.out.println("lisi = " + lisi);
//public方法,获取属性值,只读,没有set,get方法
Integer id = lisi.id();
String name = lisi.name();
String email = lisi.email();
Integer age = lisi.age();
System.out.println("id = " + id);
}
现在能查看控制台输出:
Record 通过构造方法创建了只读的对象,能够读取每个属性,不能设置新的属性值。 Record 用于创建不可变的对象,同时减少了样板代码。Record 对每个属性提供了 public 访问器,例如 lisi.name()。
Instance Methods
Record 是 Java 类,和普通 Java 类一样定义方法。下面定义方法 concat,将姓名和年龄一起打印输出。
我们创建普通的方法 concat,将 name 和 age 连接为一个字符串输出。
step1:创建实例方法
public record Student(Integer id,String name,String email,Integer age) {
public String concat(){
return String.format("姓名:%s,年龄是:%d", this.name,this.age);
}
}
step2: 调用实例方法
@Test
public void test02() {
Student student = new Student(1001, "lisi", "lisi@qq.com", 20);
//使用对象,调用实例方法
String str = student.concat();
System.out.printf("str =" + str);
}
最后控制台输出:
静态方法 Static Method
Record 类定义静态方法,试用静态方法与普通类一样。
step1: 创建静态方法
public record Student(Integer id,String name,String email,Integer age) {
public String concat(){
return String.format("姓名:%s,年龄是:%d", this.name,this.age);
}
/** 静态方法 */
public static String emailUpperCase(String email){
return Optional.ofNullable(email).orElse("no email").toUpperCase();
}
}
step2:测试静态方法
@Test
public void test03() {
//使用类,静态方法
String email = Student.emailToUppreCase("lisi@qq.com");
System.out.println("eamil = " + email);
}
Record 的构造方法
我们可以在 Record 中添加构造方法, 有三种类型的构造方法分别:是紧凑的,规范的和定制构造方法
- 紧凑型构造方法没有任何参数,甚至没有括号。
- 规范构造方法是以所有成员作为参数
- 定制构造方法是自定义参数个数
step1: 紧凑和定制构造方法
public record Student(Integer id,String name,String email,Integer age) {
/*紧凑构造方法*/
public Student{
System.out.println("id = "+ id);
if(id<1){
throw new RuntimeException("id<1");
}
}
/*自定义构造方法*/
public Student(Integer id,String name){
this(id,name,null,null);
}
}
测试:
@Test
public void test04() {
Student student = new Student(1001,"lisi");
System.out.println("student = " + student);
}
查看编译后的class文件(紧凑构造方法和规范构造方法合并了 ):
Record 与 与 Lombok
- Java Record 是创建不可变类且减少样板代码的好方法。Lombok 是一种减少样板代码的工具。两者有表面上的重叠部分。可能有人会说 Java Record 会代替 Lombok. 两者是有不同用途的工具。
- Lombok 提供语法的便利性,通常预装一些代码模板,根据您加入到类中的注解自动执行代码模板。这样的库纯粹是为了方便实现 POJO 类。通过预编译代码。将代码的模板加入到 class 中。
- Java Record 是语言级别的,一种语义特性,为了建模而用,数据聚合。简单说就是提供了通用的数据类,充当“数据载体",用于在类和应用程序之间进行数据传输。
Record 实现接口
Java Record 可以与普通类一样实现接口,重写接口的方法。
step1: 创建新的接口,定义一个规范方法。
public interface PrintInterface {
//输出自定义信息
void print();
}
step2: 创建新的 Record 实现接口,重写接口的方法,实现当前 Record 有关的业务逻辑
public record ProductRecord(Integer id, String name, Integer qty) implements PrintInterface {
@Override
public void print() {
StringJoiner joiner = new StringJoiner("-");
StringJoiner s = joiner.add(id.toString()).add(name).add(qty.toString());
System.out.println("商品信息 = " + s);
}
}
ProductRecord 实现 print()方法,打印商品详情。
step3:测试 print 方法
@Test
public void test05() {
ProductRecord productRecord = new ProductRecord(1001,"手机",200);
productRecord.print();
}
Local Record
Record 可以作为局部对象使用。在代码块中定义并使用 Record,下面定义一个 SaleRecord
step1:定义 Local Record
public static void main(String[] args) {
//定义 Java Record
record SaleRecord(String saleId,String ProductName,Double money){};
//创建 Local Record
SaleRecord saleRecord = new SaleRecord("S001","显示器",3000.01);
//使用 SaleRecord
System.out.println("saleRecord = " + saleRecord);
}
控制台输出:
嵌套 Record
多个 Record 可以组合定义, 一个 Record 能够包含其他的 Record。
我们定义 Record 为 Customer,存储客户信息,包含了 Address 和 PhoneNumber 两个 Record
step1:定义 Record
public record Address(String city,String address,String zipCode) {
}
public record Customer(String id, String name, PhoneNumber phoneNumber, Address address) {
}
public record PhoneNumber(String areaCode,String number) {
}
step2: 创建 Customer 对象
@Test
public void test07() {
Address address = new Address("大连","旅顺口区兴发路216号","10010");
PhoneNumber phoneNumber = new PhoneNumber("010","400-8080-105");
Customer customer = new Customer("C1001","李四",phoneNumber,address);
System.out.println("customer = " + customer);
String number = customer.phoneNumber().number();
System.out.println("number = " + number);
String address1 = customer.address().address();
System.out.println("address1 = " + address1);
}
控制台输出:
instanceof 判断 Record 类型
instanceof 能够与 Java Record 一起使用。编译器知道记录组件的确切数量和类型。
step1:声明 Person Record,拥有两个属性 name 和 age
public record Person(String name,Integer age) {
}
step2: 在一个业务方法判断当是 Record 类型时,继续判断 age 年龄是否满足 18 岁。
public class SomeService {
//定义业务方法,判断年龄是否18
public boolean isEligible(Object obj){
//判断 obj 为 Person 记录类型
if( obj instanceof Person(String name, Integer age)){
return age >= 18;
}
return false;
}
}
instanceof 还可以下面的方式
if( obj instanceof Person(String name, Integer age) person){
return person.age() >= 18;
}
或者
if( obj instanceof Person p){
return p.age() >= 18;
}
step3: 测试代码
@Test
public void test08() {
Person person = new Person("李四",20);
SomeService someService = new SomeService();
boolean flag = someService.isEligible(person);
System.out.println("flag = " + flag);
}
控制台输出:
处理判断中 Record 为 null
Java Record 能够自动处理 null。
step1:record 为 null
@Test
public void test09() {
SomeService someService = new SomeService();
boolean flag = someService.isEligible(null);
System.out.println("flag = " + flag);
}
控制台输出 eligible 为 false ,Debug 调试代码,发现 if 语句判断为 false,不执行
总结
- abstract 类 java.lang.Record 是所有 Record 的父类。
- 有对于 equals(),hashCode(),toString()方法的定义说明
- Record 类能够实现 java.io.Serializable 序列化或反序列化
- Record 支持泛型,例如 record Gif( T t )
- java.lang.Class 类与 Record 类有关的两个方法:
boolean isRecord() : 判断一个类是否是 Record 类型
RecordComponent[] getRecordComponents():Record 的数组,表示此记录类的所有记录组件
@Test
public void test10() {
Address address = new Address("大连","旅顺口区兴发路216号","10010");
PhoneNumber phoneNumber = new PhoneNumber("010","400-8080-105");
Customer customer = new Customer("C1001","李四",phoneNumber,address);
//判断其是否为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);
}
公众号本文地址:https://mp.weixin.qq.com/s/JNytIhxe-a-VOmq3fV4aag
欢迎关注公众号:愚生浅末
。
JDK有用的新特性-Java Record的更多相关文章
- Java JDK 1.7 和 JDK 1.8 新特性
0 引言 本文主要介绍 Java JDK 中 1.7 和 1.8 的新特性. 1 JDK 1.7 新特性 1. switch可以接受String类型: public class Switch { pu ...
- JDK 5 ~ 10 新特性倾情整理!
JDK 5 ~ 10 新特性倾情整理! 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了. 为了大家对JDK ...
- JDK 14的新特性:更加好用的NullPointerExceptions
JDK 14的新特性:更加好用的NullPointerExceptions 让99%的java程序员都头痛的异常就是NullPointerExceptions了.NullPointerExceptio ...
- 译文《全新首发JDK 16全部新特性》
封面:洛小汐 译者:潘潘 JDK 8 的新特性都还没摸透,JDK 16 的新特性就提着刀来了. 郑重申明: 第一次冒险翻译专业领域的文献,可想而知,效果特别糟糕.一般翻译文献特别是 技术专业领域 的内 ...
- java8 (jdk 1.8) 新特性——Lambda
java8 (jdk 1.8) 新特性 --初步认识 1. 什么是lambda? 目前已知的是,有个箭头 -> 说一大段官方话,也没有任何意义 我们直接看代码: 之前我们创建线程是这样的 Ru ...
- Atitit swt 4.3 4.4 4.5 新特性java attilax总结
Atitit swt 4.3 4.4 4.5 新特性java attilax总结 1. 4.5 Release - June 3, 20151 1.1. Older Releases1 2. SWT ...
- JDK 14的新特性:instanceof模式匹配
JDK 14的新特性:instanceof模式匹配 JDK14在2020年的3月正式发布了.可惜的是正式特性只包含了最新的Switch表达式,而Records,patterns,text blocks ...
- Java 16 新特性:record类
以前我们定义类都是用class关键词,但从Java 16开始,我们将多一个关键词record,它也可以用来定义类.record关键词的引入,主要是为了提供一种更为简洁.紧凑的final类的定义方式. ...
- JDK各版本新特性!
1.JDK1.5 新特性 1.自动装箱与拆箱:自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中.自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取 ...
- Java SE 6 新特性: Java DB 和 JDBC 4.0
http://www.ibm.com/developerworks/cn/java/j-lo-jse65/index.html 长久以来,由于大量(甚至几乎所有)的 Java 应用都依赖于数据库,如何 ...
随机推荐
- vue3 'alex' is defined but never used
解决方法 在package.json中的rules下加入 "no-unused-vars":"off" 即可
- java将list中某个元素放在首位
java将list中某个元素放在首位 1 List<Example> example = exampleRepository.list(); 2 3 //将list里的某个字符串默认排列在 ...
- springboot实现异步调用demo
springboot实现异步调用 异步调用特点 异步调用在开发程序中被广泛应用,在异步任务中,主线程不需要阻塞等待异步任务的完成,而是可以继续处理其他请求. 异步调用的特点如下: 非阻塞:主线程在调用 ...
- 历代iPhone及Android手机的屏幕参数对比
手机逻辑分辨率Point,也就是CSS像素,是进行网页适配的关键,以下是平时整理的一些备忘录数据,可以收藏. 屏幕清晰度分类 SD标清 HD高清(2倍屏) FHD全高清(3倍屏) QHD倍高清(4倍屏 ...
- [oeasy]python0093_电子游戏起源_视频游戏_达特茅斯_Basic_家酿俱乐部
编码进化 回忆上次内容 Ed Robert 的 创业之路 从 售卖 diy 组装配件 到进军 计算器市场 最后 发布 牛郎星8800 intel 8080 的出现 让 人人都有 自己的 个人电脑 Bi ...
- 靶机练习: y0usef
靶机: y0usef 准备工作 靶机地址: https://download.vulnhub.com/y0usef/y0usef.ova MD5 校验:28c5d869b003be94b2d8ab4b ...
- Django 不通过外键实现多表关联查询
Django不通过外键实现多表关联查询 by:授客 QQ:1033553122 测试环境 Win 10 Python 3.5.4 Django-2.0.13.tar.gz 需求 不通过外键,使 ...
- HTML+JavaScript+CSS做一个界面
下面是一个web界面主要是前端没有后端功能:关于JavaScript几种比较常见的样式 Javaweb(1),html <!DOCTYPE html> <html lang=&q ...
- Python的GDAL库绘制多波段、长时序遥感影像时间曲线图
本文介绍基于Python中的gdal模块,对大量长时间序列的栅格遥感影像文件,绘制其每一个波段中.若干随机指定的像元的时间序列曲线图的方法. 在之前的文章中,我们就已经介绍过基于gdal模块, ...
- Continue-AI编程助手本地部署llama3.1+deepseek-coder-v2
领先的开源人工智能代码助手.您可以连接任何模型和任何上下文,以在 IDE 内构建自定义自动完成和聊天体验 推荐以下开源模型: 聊天:llama3.1-8B 推理代码:deepseek-coder-v2 ...