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的更多相关文章

  1. 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 ...

  2. JDK 5 ~ 10 新特性倾情整理!

    JDK 5 ~ 10 新特性倾情整理! 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了. 为了大家对JDK ...

  3. JDK 14的新特性:更加好用的NullPointerExceptions

    JDK 14的新特性:更加好用的NullPointerExceptions 让99%的java程序员都头痛的异常就是NullPointerExceptions了.NullPointerExceptio ...

  4. 译文《全新首发JDK 16全部新特性》

    封面:洛小汐 译者:潘潘 JDK 8 的新特性都还没摸透,JDK 16 的新特性就提着刀来了. 郑重申明: 第一次冒险翻译专业领域的文献,可想而知,效果特别糟糕.一般翻译文献特别是 技术专业领域 的内 ...

  5. java8 (jdk 1.8) 新特性——Lambda

    java8 (jdk 1.8) 新特性 --初步认识 1. 什么是lambda? 目前已知的是,有个箭头  -> 说一大段官方话,也没有任何意义 我们直接看代码: 之前我们创建线程是这样的 Ru ...

  6. 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  ...

  7. JDK 14的新特性:instanceof模式匹配

    JDK 14的新特性:instanceof模式匹配 JDK14在2020年的3月正式发布了.可惜的是正式特性只包含了最新的Switch表达式,而Records,patterns,text blocks ...

  8. Java 16 新特性:record类

    以前我们定义类都是用class关键词,但从Java 16开始,我们将多一个关键词record,它也可以用来定义类.record关键词的引入,主要是为了提供一种更为简洁.紧凑的final类的定义方式. ...

  9. JDK各版本新特性!

    1.JDK1.5 新特性 1.自动装箱与拆箱:自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中.自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取 ...

  10. Java SE 6 新特性: Java DB 和 JDBC 4.0

    http://www.ibm.com/developerworks/cn/java/j-lo-jse65/index.html 长久以来,由于大量(甚至几乎所有)的 Java 应用都依赖于数据库,如何 ...

随机推荐

  1. “古剑山”初赛Misc 幸运饼干

    "古剑山"初赛Misc 幸运饼干 考点:Chrome的Cookies解密 赛中思路 bandzip极限压缩hint.jpg后打明文攻击 压缩包密码:sv@1v3z ┌──(root ...

  2. 羊城杯决赛Misc

    羊城杯决赛Misc easy00aes比赛时没离线0宽环境摆了 LmqHmAsk没思路,赛后看着群里各位师傅讨论才明白预期解,wp里直接放toto师傅的脚本了 这里放个toto师傅博客: https: ...

  3. 算法金 | 推导式、生成器、向量化、map、filter、reduce、itertools,再见 for 循环

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 不要轻易使用 For 循环 For 循环,老铁们在编程中经常用到的一个基本结构,特别是 ...

  4. 一个难忘的json反序列化问题

    前言 最近我在做知识星球中的商品秒杀系统,昨天遇到了一个诡异的json反序列化问题,感觉挺有意思的,现在拿出来跟大家一起分享一下,希望对你会有所帮助. 案发现场 我最近在做知识星球中的商品秒杀系统,写 ...

  5. SpringBoot集成实时通讯WebSocket和其它代替方案

    WebSocket 双向实时通讯 一.添加WebSocketConfig配置类 /** * 开启WebSocketConfig */ @Configuration public class WebSo ...

  6. oeasy 教您玩转 linux 之 010302 火狐浏览器 firefox

    我们来回顾一下 上一部分我们都讲了什么? oneko xeyes 这次看看这个火狐 火狐 看看当前版本 看看是否可以更新 如果需要更新就更新    firefox -v    apt search f ...

  7. ASP.NET Core 程序集注入(二)

    public void ConfigureServices(IServiceCollection services) { string strValue = Configuration.GetSect ...

  8. Sysbench 使用总结

    Sysbench使用总结 实践环境 CentOS 7.8 Sysbench 1.0.20 下载地址:https://github.com/akopytov/sysbench/archive/refs/ ...

  9. 彻底搞懂python super函数的作用

    super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了. 调用父类同名方法有两种方式: 1.调 ...

  10. 图解翻转单向链表,超详细(python语言实现)

    节点类: 1 class ListNode(object): 2 def __init__(self, x): 3 self.val = x 4 slef.next = None 反转单向链表的函数如 ...