Java 14 发布了,可以扔掉Lombok了?
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.java
Note: 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都还没用熟~
参考资料:
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
Java 14 发布了,可以扔掉Lombok了?的更多相关文章
- JDK/Java 14 发布
3 月 17 日,JDK/Java 14 正式 GA. 此版本包含的 JEP(Java/JDK Enhancement Proposals,JDK 增强提案)比 Java 12 和 13 加起来的还要 ...
- Java 14 发布了,再也不怕 NullPointerException 了!
2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 358: Helpful NullPoint ...
- Java 8 到 Java 14,改变了哪些你写代码的方式?
前几天,JDK 14 正式发布了,这次发布的新版本一共包含了16个新的特性. 其实,从Java8 到 Java14 ,真正的改变了程序员写代码的方式的特性并不多,我们这篇文章就来看一下都有哪些. La ...
- Java 14 祭出代码简化大器,Lombok 要被干掉了?
Java 14 3 月发布距现在已经发布 2 个多月,发布了很多新特性,详细的新特性介绍可以看这篇文章: http://www.javastack.cn/article/2020/java14-has ...
- Java 14 开箱,它真香香香香
Java 14 已经发布有一周时间了,我准备来开个箱,和小伙伴们一起来看看新特性里面都有哪些好玩的.我们程序员应该抱着尝鲜.猎奇的心态,否则就容易固步自封,技术停滞不前.先来看看 Java 14 都有 ...
- 我把自己的java库发布到了maven中央仓库,从此可以像Jackson、Spring的jar一样使用它了
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Java 14 可能带来什么新特性?
JDK/Java 13 在一个月前已经发布,该版本带来了 5 大新特性,笔者观察到其中的 Text Blocks(文本块)特性似乎被讨论最多. 文本块特性与常见的 Python "" ...
- Java 14 都要来了,为什么还有这么多人固守Java8?
作者:刘欣 从Java 9开始,Java版本的发布就让人眼花缭乱了. 每隔6个月,都会冒出一个新版本出来,Java 10 , Java 11, Java 12, Java 13, 到2020年3月份, ...
- Java 14 令人期待的 5 大新特性,打包工具终于要来了
随着新的 Java 发布生命周期的到来,新版本预计将于 2020 年 3 月发布,本文将对其中的 5 个主要特性作些概述. Java 13刚刚发布给开发人员使用不久,最新版本的JDK于2019年9月发 ...
随机推荐
- android apk 文件反编译
最近,自己坑逼的把一个android 项目修改版本的代码删除了.这个项目居然还没上传到源代码管理器.幸好还有apk文件,修改的代码也不多可以反编译一下. 1.下载 dex2jar 获取源码工具 地 ...
- Java IO: System.in, System.out, System.err
原文链接 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) System.in, System.out, System.err这3个流同样是常见的数据来 ...
- 吴裕雄--天生自然 R语言开发学习:高级数据管理(续三)
#-----------------------------------# # R in Action (2nd ed): Chapter 5 # # Advanced data management ...
- java 实体类中日期格式转换
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss&quo ...
- Uber自动驾驶卡车正式运营,是否会给卡车司机彻底“宣判死刑”?
随着科技的快速迭进和嬗变,大众的生活也在被全面革新和改变.不过有些改变是显性的,比如PC和智能手机的出现.有些改变却是隐性的,比如太空科技.云计算等.而在当下,又一个看似与大众生活紧密相关,但一般人却 ...
- Mercurial 小结
基本操作 # 拉取 并 更新 pull pull && hg update # 撤销上一个命令(不能重复运行) hg rollback # 恢复到指定的 changeset hg st ...
- windows应用程序单实例
前言 这才第几天博客就跟不上了,看来一天一篇博客的目标还是有点大,写博客还是挺费时间的,写了不满意删,删完再写...直到自己没了耐心.今天先写个前言,实质性的内容明天再补吧.今天一天的收获还是挺多的, ...
- History of AI
人工智能的历史源远流长.在古代的神话传说中,技艺高超的工匠可以制作人造人,并为其赋予智能或意识.[1]现代意义上的AI始于古典哲学家用机械符号处理的观点解释人类思考过程的尝试.20世纪40年代基于抽象 ...
- Leetcode 703题数据流中的第K大元素(Kth Largest Element in a Stream)Java语言求解
题目链接 https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/ 题目内容 设计一个找到数据流中第K大元素的类(class) ...
- mysql插入数据报错一二
上周selenium+phantomjs+python3简单爬取一个网站,往数据库写数据遇到以下两个问题,记录一下: 报错一:Data truncated for column 'update_tim ...