记录是类的语法糖吗?

21
我最近发现了Java的records,了解到它们的存在和目的真是令人惊叹。
然而,我开始想知道它们是否本质上只是幕后的类。
这是否意味着在编译过程中,它们会被转换为具有最终私有字段、公共构造函数和必要的getter方法的显式类呢?

15
引用JEP 395: Records中的一句话:“通过增强Java编程语言的记录,它们是作为不可变数据的透明载体的。”(我强调)。总共,JEP 395中提到了86次“类”和63次“类”。基本上,在Java中,除了基本类型,几乎所有的东西都是类,所以记录也是类并不奇怪。 - undefined
4
这真的取决于你对于“语法糖”这个词的确切理解,大多数人对于这个词的含义并没有一个明确的定义。正如马克指出的,记录(Records)确实是类(classes)。但是,它们是否只是“常规类的语法糖”这个问题,如果没有一个明确的定义,很难回答。 - undefined
3
鉴于记录模式(JEP 440: 记录模式)仅适用于记录,我可以说记录并不仅仅是类的语法糖,因为它们提供了对于“普通”类不可用的功能。 - undefined
2
@supercat:这个指南有点毫无意义吧?如果JIT优化器能够确定场景的参数,它就可以始终执行操作(类似于C++的as-if规则)。Record的限制可能会让编译器作者更容易做一些事情,但正如答案所指出的那样,在底层,它只是一个具有特定设计的类,唯一的独特之处在于它继承自java.lang.Record(它本身没有任何有意义的行为,只是被序列化和记录模式特别识别)。 - undefined
3
如果你把这个论点推到极端,那么所有的编程语言都只是汇编语言的语法糖(而汇编语言本身只是机器码的语法糖,机器码又只是内存中的位的语法糖,以此类推...)。这就是为什么使用模糊/灵活的“语法糖”定义通常是无意义的原因:你得到的是空洞的真实陈述。它们并没有错,但也没有告诉你关于你正在检查的特性有任何有用的信息。 - undefined
显示剩余5条评论
1个回答

36
在底层,它仍然会创建一个类(该类派生自java.lang.Record)。
你可以自己试一试:
// test.java
record Test(int foo, String bar) {}

当你使用javac test.java编译它,然后再用javap Test反汇编它,你将得到以下代码:
final class Test extends java.lang.Record {
  Test(int, java.lang.String);
  public final java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public int foo();
  public java.lang.String bar();
}

在机器代码级别上呢?例如,如果一个函数创建并返回一个具有特定字段值的Record,而不保留对该对象的任何其他引用,并且调用者在获取字段值后丢弃了所有对该对象的引用,那么JVM是否能够生成避免创建和丢弃对象实例的机器代码? - undefined
14
Java不关心机器码级别,这是JVM的实现细节。显然,“记录”不会奇迹般地利用CPU上以前未使用的指令或访问以前无法访问的寄存器或内存区域,它们最终只是一种特殊类型的类。但通过检查机器码级别来定义一个特性在Java中是否是“语法糖”,就好比是用扫描电子显微镜检查单个焊接点来询问如何建造一架飞机:你会找到一些东西,但可能会错过整个重点。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接