枚举名是用Java实现的吗?

Ole*_*eev 55 java enums

枚举名是用Java实现的吗?

即保证enum1.name() == enum2.name()在同名的情况下?与enum.name()保证被实习的字符串进行比较是否安全.

das*_*ght 50

虽然没有明确的保证,但最终结果必然会使enum具有相同名称的常量的比较总是成功:

enum A {enum1};
enum B {enum1};
System.out.println(A.enum1.name() == B.enum1.name()); // Prints "true"
Run Code Online (Sandbox Code Playgroud)

这样做的原因是Java编译器Enum以这样的方式构造子类,它们最终调用Enum唯一受保护的构造函数,并将enum值传递给它:

protected Enum(String name, int ordinal);
Run Code Online (Sandbox Code Playgroud)

该名称以字符串文字的形式嵌入到生成的代码中.根据String文件,

所有文字字符串和字符串值常量表达式都是实体.

enum常量名称相同时,这相当于表达式的隐式保证.但是,我不会依赖这种行为,equals(...)而是使用它,因为任何阅读我的代码的人都会摸不着头脑,以为我犯了一个错误.

  • @supercat所有字符串字面获得通过,以[`String.intern`(http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern())方法,确保所有包中的字符串文字为相同的字符串生成相同的对象. (7认同)

Pet*_*ček 33

没有.

Dasblinkenlight的答案是我们迄今为止的最佳答案.在那里他说:

这样做的原因是Java编译器Enum以这样的方式构造子类 ,它们最终调用Enum's单独的受保护构造函数,并将其传递给enum值的名称

在那里他们得到实习,因为他们是字符串常量.

但是,在JLS,8.9.2,Enum Body声明中,有这样的:

实际上,编译器可能通过在Enum类型的默认构造函数中声明Stringint参数来镜像enum类型.但是,这些参数未指定为"隐式声明",因为不同的编译器不需要就默认构造函数的形式达成一致.只有enum类型的编译器知道如何实例化enum常量; 其他编译器可以简单地依赖于类型的隐式声明public static 字段enum(第8.9.3节),而不考虑这些字段的初始化方式.

(强调我的)

所以我们将调用构造函数,但我们不会以任何特定的方式执行它,我们可以在编译器中管理自己的构造函数.

因此,我完全有可能编写一个正确且符合JLS的Java编译器,它不会以某种方式实现名称,可能是因为没有将名称存储为文字.是的,它会故意以恶意破坏您的代码为目的,但这将是每个规范的正确行为.


实际说,是的.

每个理智的实现都会实现字符串.我认为假设这种行为是安全的.但是,这并不能保证,因此如果我在实际代码中看到这一点,即使在评论中对其进行了详细描述,我也会对它非常不满意.

请不要依赖这种未指定和特定于实现的行为.如果你真的,真的必须,为它写一个单元测试.并assert在代码中加入了许多解释.衡量你的方法是否真的会做任何事情.

在使用它们之前,请考虑手动循环enum成员的名称和intern()手动名称.这样,它将立即清楚你正在做什么.这不能可靠地工作.看评论.

  • "考虑循环遍历枚举成员的名称和`intern()`手动"我不认为这会起作用.`intern()`返回规范字符串,如果之前插入了另一个实例,则该字符串将不是您传入的同一实例. (2认同)