写点什么

谈 Java Record 类

作者:ES_her0
  • 2022 年 7 月 15 日
  • 本文字数:1149 字

    阅读完需:约 4 分钟

偶尔刷一刷各大中文技术社区,还有很多标题还是“Java 8 的新特性”等等,对于一个 10 年前发布的版本可能真的称不上“新”了。但不可忽视的是,现在业务保有量最大的版本确实还是 8,继续深究 Java8 也完全没问题。没有追捧新技术的意思,但技术在进步,我们也应该打开视野,保有量第二的已经到了 11 了,虽然 11 也是 LTS,但维护截止日期与 8 仅差 1 年,恰好 17 在 2021 年 9 月就正式发布,所以你的下一个版本的最佳选择应该是 17。这里就再谈一下 Java17 正式发布的 record 类。

什么是 Record

Record 类在 Java14 中就开始预览,一直到最近的一个 LTS 版本——Java17 才正式发布。根据 JEP395 的描述,Record 类是不可变数据的载体,类似于当下广泛应用的各种 model,dto,vo 等 POJO 类,但 record 本身在构造之后遍不再可赋值。所有的 record 类都继承自 java.lang.Record。

Record 提供了什么

record 类默认提供了全字段的构造器,属性的访问,还有 equals,hashcode,toString 方法。可能乍一看这不就是 lombok 吗,或者熟悉 kotlin 的会觉得这就是 data class 啊。确实,功能性上区别大不,除了 record 是不可变的。下面是一个 record 类型的定义:


record Rectangle(double length, double width) { }
复制代码


如果用 lombok 就是下面这样:

@Datapublic Rectangle{    private double length;    private double width;}
复制代码


两者的区别在于,对于 equals,hashcode,toString 等方法,record 的字节码使用了 invokedynamic,而 lombok 使用的是普通的 invokestatic 等,性能要比后者高出很多。

Record 怎么用


如果仅仅用于传统的 POJO 类的替换,其实可读性要差很多。因为 record 默认只提供了全字段的构造器,需要这样写:

Rectangle r = new Rectangle(4,5);
复制代码


两个字段可能还好点,但通常我们需要 10 个或者更多的字段时,这种初始化看着就头大。当然,record 类支持自定义构造器,也可以支持了一些简化操作,但跟 lombok 的 @Builder 还是没法比。是不是就应用用在字段比较少的情况下呢?个人觉得 record 的一个重要用法就是存储方法内的临时数据对象,举个例子:

public List<Person> sortPeopleByAge(List<Person> people) {        record Data(Person person, int age){};
return people.stream() .map(person -> new Data(person, computeAge(person))) .sorted((d1, d2) -> Double.compare(d2.age(), d1.age())) .map(Data::person) .collect(toList());}public int computAge(Person person) { return person.getAge();}
复制代码

上面的代码是把 Person 对象按照年龄排序,如果不是 record 构建一个临时存储对象,需要怎么实现呢,相对来说通过这种流式写法还是比较费劲的。

小结

Record 类从性能上说要远比 lombok 强,毕竟是亲生的。但 record 类更适合用做方法的临时内部数据存储,可以很大程度上提升可读性。

用户头像

ES_her0

关注

还未添加个人签名 2018.03.21 加入

还未添加个人简介

评论

发布
暂无评论
谈Java Record类_7月月更_ES_her0_InfoQ写作社区