Java 为什么可以';是否将枚举和记录合并?

Java 为什么可以';是否将枚举和记录合并?,java,enums,java-record,Java,Enums,Java Record,最近我刚刚创建了另一个枚举类型。我利用了一个事实,即在Java中,枚举是一种特殊类型的类(而不是像C#那样的类)。我使用了两个字段,一个全参数构造函数和两个字段的getter 这是一个例子: enum NamedIdentity{ 约翰(1,“杀人犯约翰”), 吉尔(2,“女射手吉尔”); int-id; 字符串昵称; NamedIdentity(int-id,字符串昵称){ this.id=id; this.昵称=昵称; } id(){ 返回此.id; } 字符串昵称(){ 返回这个昵称; }

最近我刚刚创建了另一个枚举类型。我利用了一个事实,即在Java中,枚举是一种特殊类型的类(而不是像C#那样的类)。我使用了两个字段,一个全参数构造函数和两个字段的getter

这是一个例子:

enum NamedIdentity{
约翰(1,“杀人犯约翰”),
吉尔(2,“女射手吉尔”);
int-id;
字符串昵称;
NamedIdentity(int-id,字符串昵称){
this.id=id;
this.昵称=昵称;
}
id(){
返回此.id;
}
字符串昵称(){
返回这个昵称;
}
}
然后我想Java14的
record
keyword会为我保存这个特性提供给我的样板代码。据我所知,这并不与
enum
s相结合。如果存在枚举记录,则上述代码如下所示:

enum记录NamedIdentity(int-id,字符串昵称){
约翰(1,“杀人犯约翰”),
吉尔(2,“女射手吉尔”);
}
我的问题是:枚举记录不存在有什么原因吗?我可以想象几个原因,包括但不限于:

  • 这个特性的用例数量太少,如果我们作为Java语言设计者设计和实现其他特性,Java语言将受益更多
  • 由于枚举类型的内部实现,这很难实现
  • 作为Java语言设计师,我们根本没有考虑到这一点,或者我们还没有收到来自社区的这样一个请求,所以我们没有优先考虑它
  • 此功能可能存在语义问题,或者此功能的实现可能导致语义歧义或其他混淆
tl;博士
  • 技术限制:多重继承防止将
    Enum
    Record
    超类混合
  • 解决方法:保留
    记录作为枚举的成员字段
NamedIdentity.JILL.detail.昵称()//➣ “射手吉尔”
多重继承 你问:

是否存在枚举记录不存在的原因

技术原因是,在Java中,每个枚举隐式地是类的子类,而每个记录隐式地是类的子类

Java不支持多重继承。因此,这两者不能结合起来

语义学 但更重要的是语义

枚举用于在编译时声明一组有限的命名实例。加载枚举类时,将实例化每个枚举对象。在运行时,我们不能再实例化hat类的任何对象(好吧,也许使用极端反射/内省代码,但我将忽略这一点)

Java中的记录不会自动实例化。通过调用
new
,您的代码可以实例化该类中任意数量的对象。所以一点也不一样

减少样板文件不是
record
你说:

我以为Java14的record关键字会为我保存样板代码

您误解了录制功能的目的。我建议你阅读并观看布赖恩·戈茨关于这一主题的最新演讲

正如所述,
record
的目标不是减少样板文件。这种减少是一种令人愉快的副作用,但不是发明
记录的原因

记录在形式上是一个“名义元组”。元组是指按一定顺序排列的各种类型的值的集合,或者如维基百科所说:“元素的有限有序列表(序列)”。“标称”是指每个元素都有一个名称

记录意味着一个简单而透明的数据载体。透明意味着它的所有成员字段都是公开的。更好的方法是简单地命名为与字段相同的名称,而不使用JavaBeans的
get…
约定。
hashCode
equals
的默认植入是检查每个成员字段。记录的目的是关注所携带的数据,而不是行为(方法)

此外,一个记录意味着表面上是不可变的。不可变意味着您不能更改记录实例中的原语值,也不能更改对象引用。记录实例中的对象本身可能是可变的,这就是我们所说的浅显含义。但记录自身字段的值(原语值或对象引用)不能更改。不能将替换对象重新指定为记录的成员字段之一

  • 当编译时已知的实例集有限时,请使用
    enum
  • 当您编写的类的主要任务是不可变且透明地携带一组数据字段时,请使用
    record
值得一提的问题 我可以看到这两个概念的交叉点,在编译时我们知道一组有限的命名值的不可变透明集合。所以你的问题是正确的,但不是因为样板文件的减少。询问Brian Goetz或Java团队中的其他人是否讨论过这个概念是很有趣的

解决方法:在
enum
解决方法非常简单:在枚举上保留一个
记录
实例。

可以将记录传递给枚举构造函数,并将该记录作为成员字段存储在枚举定义中

将成员字段设置为“最终”
。这就是我们的枚举。因此,不需要标记为private,也不需要添加getter方法

首先是
记录
定义

package org.example;
公共记录执行者(int-id,字符串昵称)
{
}
接下来,我们将
record
的一个实例传递给enum构造函数

package org.example;
公共枚举名称实体
{
约翰(新表演者)(1,“屠夫约翰