2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载。在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 359: Records

官方吐槽最为致命

早在2019年2月份,Java 语言架构师 Brian Goetz,曾经写过一篇文章(http://cr.openjdk.java.net/~briangoetz/amber/datum.html ),详尽的说明了并吐槽了Java语言,他和很多程序员一样抱怨“Java太啰嗦”或有太多的“繁文缛节”,他提到:开发人员想要创建纯数据载体类(plain data carriers)通常都必须编写大量低价值、重复的、容易出错的代码。如:构造函数、getter/setter、equals()、hashCode()以及toString()等。

以至于很多人选择使用IDE的功能来自动生成这些代码。还有一些开发会选择使用一些第三方类库,如Lombok等来生成这些方法,从而会导致了令人吃惊的表现(surprising behavior)和糟糕的可调试性(poor debuggability)。

那么,Brian Goetz 大神提到的纯数据载体到底指的是什么呢。他举了一个简单的例子:

final class Point {public final int x;public final int y;public Point(int x, int y) {this.x = x;this.y = y;}// state-based implementations of equals, hashCode, toString// nothing else}

这里面的Piont其实就是一个纯数据载体,他表示一个"点"中包含x坐标和y坐标,并且只提供了构造函数,以及一些equals、hashCode等方法。

于是,BrianGoetz大神提出一种想法,他提到,Java完全可以对于这种纯数据载体通过另外一种方式表示。

其实在其他的面向对象语言中,早就针对这种纯数据载体有单独的定义了,如Scala中的case、Kotlin中的data以及C#中的record。这些定义,尽管在语义上有所不同,但是它们的共同点是类的部分或全部状态可以直接在类头中描述,并且这个类中只包含了纯数据而已。

于是,他提出Java中是不是也可以通过如下方式定义一个纯数据载体呢?

record Point(int x, int y) { }

神说要用record,于是就有了

就像大神吐槽的那样,我们通常需要编写大量代码才能使类变得有用。如以下内容:

  • toString()方法

  • hashCode() and equals()方法

  • Getter 方法

  • 一个共有的构造函数

对于这种简单的类,这些方法通常是无聊的、重复的,而且是可以很容易地机械地生成的那种东西(ide通常提供这种功能)。

当你阅读别人的代码时,可能会更加头大。例如,别人可能使用IDE生成的hashCode()和equals()来处理类的所有字段,但是如何才能在不检查实现的每一行的情况下确定他写的对呢?如果在重构过程中添加了字段而没有重新生成方法,会发生什么情况呢?

大神Brian Goetz提出了使用record定义一个纯数据载体的想法,于是,Java 14 中便包含了一个新特性:EP 359: Records ,作者正是 Brian Goetz

Records的目标是扩展Java语言语法,Records为声明类提供了一种紧凑的语法,用于创建一种类中是“字段,只是字段,除了字段什么都没有”的类。通过对类做这样的声明,编译器可以通过自动创建所有方法并让所有字段参与hashCode()等方法。这是JDK 14中的一个预览特性。

一言不合反编译

Records的用法比较简单,和定义Java类一样:

record Person (String firstName, String lastName) {}

如上,我们定义了一个Person记录,其中包含两个组件:firstName和lastName,以及一个空的类体。

那么,这个东西看上去也是个语法糖,那他到底是怎么实现的那?

我们先尝试对他进行编译,记得使用--enable-preview参数,因为records功能目前在JDK 14中还是一个预览(preview)功能。

javac --enable-preview --release 14 Person.javaNote: Person.java uses preview language features.Note: Recompile with -Xlint:preview for details.

如前所述,Record只是一个类,其目的是保存和公开数据。让我们看看用javap进行反编译,将会得到以下代码:

public final class Person extends java.lang.Record {private final String firstName;private final String lastName;public Person(java.lang.String, java.lang.String);public java.lang.String toString();public final int hashCode();public final boolean equals(java.lang.Object);public java.lang.String firstName();public java.lang.String lastName();}

通过反编译得到的类,我们可以得到以下信息:

1、生成了一个final类型的Person类(class),说明这个类不能再有子类了。

2、这个类继承了java.lang.Record类,这个我们使用enum创建出来的枚举都默认继承java.lang.Enum有点类似

3、类中有两个private final 类型的属性。所以,record定义的类中的属性都应该是private final类型的。

4、有一个public的构造函数,入参就是两个主要的属性。如果通过字节码查看其方法体的话,其内容就是以下代码,你一定很熟悉:

public Person(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}

5、有两个getter方法,分别叫做firstName和lastName。这和JavaBean中定义的命名方式有区别,或许大神想通过这种方式告诉我们record定义出来的并不是一个JavaBean吧。

6、还帮我们自动生成了toString(), hashCode() 和 equals()方法。值得一提的是,这三个方法依赖invokedynamic来动态调用包含隐式实现的适当方法。

还可以这样玩

前面的例子中,我们简单的创建了一个record,那么,record中还能有其他的成员变量和方法吗?我们来看下。

1、我们不能将实例字段添加到record中。但是,我们可以添加静态字段。

record Person (String firstName, String lastName) {static int x;}

2、我们可以定义静态方法和实例方法,可以操作对象的状态。

record Person (String firstName, String lastName) {static int x;public static void doX(){x++;}public String getFullName(){return firstName + " " + lastName;}}

3、我们还可以添加构造函数。

record Person (String firstName, String lastName) {static int x;public Person{if(firstName == null){throw new IllegalArgumentException( "firstName can not be null !");}}public Person(String fullName){this(fullName.split(" ")[0],this(fullName.split(" ")[1])}}

所以,我们是可以在record中添加静态字段/方法的,但是问题是,我们应该这么做吗?

请记住,record推出背后的目标是使开发人员能够将相关字段作为单个不可变数据项组合在一起,而不需要编写冗长的代码。这意味着,每当您想要向您的记录添加更多的字段/方法时,请考虑是否应该使用完整的类来代替它。

总结

record 解决了使用类作为数据包装器的一个常见问题。纯数据类从几行代码显著地简化为一行代码。

但是,record目前是一种预览语言特性,这意味着,尽管它已经完全实现,但在JDK中还没有标准化。

那么问题来了,如果你用上了Java 14之后,你还会使用Lombok吗?哦不,你可能短时间内都用不上,因为你可能Java 8都还没用熟~

PS:最近Java 14发布了很多新功能,很多特性还是比较有意思的,这个是本系列的第一篇文章,欢迎大家关注公众号:Java之道,后续文章写好后会第一时间发出。

参考资料:

https://openjdk.java.net/jeps/359

https://dzone.com/articles/a-first-look-at-records-in-java-14

https://aboullaite.me/java-14-records/

http://cr.openjdk.java.net/~briangoetz/amber/datum.html

关于作者Hollis,一个对Coding有着独特追求的人,现任阿里巴巴技术专家,个人技术博主,技术文章全网阅读量数千万,《程序员的三门课》联合作者。

转载自 微信公众号 Java之道

Java 14 发布了,终于可以扔掉Lombok了?相关推荐

  1. Java 14 发布了,不使用class也能定义类了?还顺手要干掉Lombok!

    2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 359: Records 官方吐槽最为致命 ...

  2. Java 14 发布!不使用class也能定义类了?还顺手要干掉Lombok!

    2020 年 3 月 17 日,JDK/Java 14 正式 GA(General Available). JDK14特性一览: JEP 305: Pattern Matching for insta ...

  3. JDK/Java 14 发布

    3 月 17 日,JDK/Java 14 正式 GA. 此版本包含的 JEP(Java/JDK Enhancement Proposals,JDK 增强提案)比 Java 12 和 13 加起来的还要 ...

  4. Java 14 发布了,再也不怕NullPointerException 了!?

    △Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 258篇原创分享 作者 l Hollis 来源 l Java之道(ID:javaways) 2020年3月17日发布,Ja ...

  5. Java 14 发布了,再也不怕 NullPointerException 了!

    2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 358: Helpful NullPoint ...

  6. djano 字段不重复_Java 14 发布了,不使用quot;classquot;也能定义类了?还顺手要干掉Lombok!...

    2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 359: Records 官方吐槽最为致命 ...

  7. java 8代码 改 java7_Java 8 到 Java 14,改变了哪些你写代码的方式?

    前几天,JDK 14 正式发布了,这次发布的新版本一共包含了16个新的特性. 其实,从Java8 到 Java14 ,真正的改变了程序员写代码的方式的特性并不多,我们这篇文章就来看一下都有哪些. La ...

  8. Java 8 到 Java 14,改变了哪些你写代码的方式?

    前几天,JDK 14 正式发布了,这次发布的新版本一共包含了16个新的特性. 其实,从Java8 到 Java14 ,真正的改变了程序员写代码的方式的特性并不多,我们这篇文章就来看一下都有哪些. La ...

  9. 七、Java 14 新特性

    七.Java 14 新特性 Java 14 已如期于 2020 年 3 月 17 日正式发布,此次更新是继半年前 Java 13 这大版本发布之后的又一次常规版本更新,即便在全球疫情如此严峻形势下,依 ...

最新文章

  1. Stumpwm的编译安装
  2. Python编程基础:第九节 逻辑运算Logical Operators
  3. html5中外描边怎么写,CSS3实现文字描边的2种方法(小结)
  4. 经典二分:秦腾与教学评估
  5. JS中与正则相关的方法
  6. php study 直接显示代码_《细说PHP》第四版 样章 第18章 数据库抽象层PDO 12
  7. 《智慧书》格言91-100
  8. 嘉年华,历数风流人物
  9. 金融IT和ERP,哪个更有前途?
  10. 豪沃轻abs12v电是什么系统_汽车中的ABS系统是什么意思?
  11. 记录使用mybatis-plus时遇到的错误
  12. python中seth和fd_Python turtle.fd方法代码示例
  13. SQLServer 数据库无法重命名
  14. 【UOJ 454】打雪仗(通信题)(分块)
  15. cocoscreator的游戏背景适配方案
  16. 【POI2005】SZA-Template(KMP)
  17. 关于极光推送报错6003的一些问题
  18. C语言关键字浅析-double
  19. 关于实现uni-app项目在APP端使用微信支付功能
  20. IDEA更换主题背景为黑色和设置背景图片并设置字体大小

热门文章

  1. spring的aop配置-配置将通知织入目标对象
  2. 享元设计模式coding
  3. mysql+encode+decode+错误_mysql decode encode 乱码问题
  4. WIN10安装ubuntu全过程
  5. Jquery+php+ajax实现表单异步提交,动态添加回复评论
  6. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)- 分组(矩阵快速幂套NTT优化dp)
  7. CodeForces - 1549F1 Gregor and the Odd Cows (Easy)(几何+数论)
  8. HDU - 5788 Level Up(主席树+dfs序+树状数组)
  9. PAT (Basic Level) 1055 集体照(模拟,好题)
  10. 自学JAVA5.18