枚举名称是在Java中实现的吗?

枚举名称是在Java中实现的吗?

即保证enum1.name() == enum2.name()在相同名称的情况下? 将enum.name()与保证被实现的string进行比较是安全的。

尽pipe没有明确的保证,但最终的结果必然是这样的:比较总是能够得到相同名称的enum常量:

 enum A {enum1}; enum B {enum1}; System.out.println(A.enum1.name() == B.enum1.name()); // Prints "true" 

原因是Java编译器构造了Enum子类,使得它们最终调用Enum的唯一受保护的构造函数,并将其传递给enum值的名称:

 protected Enum(String name, int ordinal); 

该名称以string文本formsembedded到生成的代码中。 根据String文档,

所有文字string和string值的常量expression式都被禁用。

enum常量的名称相同时,这相当于隐式保证了expression式成功。 但是,我不会依赖这种行为,而是使用equals(...) ,因为任何阅读我的代码的人都会挠头,认为我犯了一个错误。

没有。

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

原因是Java编译器构造了Enum子类,使得它们最终调用Enum's唯一受保护的构造函数,并将enum的名称

在那里他们被拦截,因为他们是string常量。

但是,在JLS 8.9.2中,Enum Body Declarations就是这样的:

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

(重点是我的)

所以我们将调用构造函数,但是我们不必以任何特定的方式来做,而且我们可以在编译器中pipe理自己的构造函数。

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


实际上说,是的。

每个理智的实现都会实习string。 我想说这种行为是安全的。 但是这并不能保证,所以如果我用真实的代码来看这个,即使在评论中对它进行了彻底的描述,我也会非常不满意它。

请不要依赖这种不明确的和特定于实现的行为。 如果你真的,真的必须写一个unit testing。 并在代码中joinassert ,并进行大量的解释。 衡量你的方法是否真的会做任何事情。

考虑循环使用enum成员的名字和intern()他们之前手动。 那样的话,你将会马上清楚你在做什么。 这不能可靠地工作。 看评论。

使用string,你将要使用string的equals方法。 除此之外,你已经有了可以和平等运算符比较的枚举。 在什么情况下会出现这种情况?

这就是说,是的,.equals方法将返回true,如果他们是相同的。

我不确定平等运营商,如果没有查询,我可以告诉你,如果是这样的话,那么使用它就是糟糕的编程。

关于Enum的Oracle文档说(第一行):

枚举types是一种特殊的数据types,它使一个variables成为一组预定义的常量。 该variables必须等于为其预定义的值之一 。 常见的例子包括指南针的方向(北,南,东,西)和一周中的日子。

如果这是真的,那么,是的,如果名称相同,则enum1.name() == enum2.name()将保证为真。

另外,在方法name() javadoc中:

public final String name()返回此枚举常量的名称,与其枚举声明中声明的完全相同。 大多数程序员应该优先使用toString()方法,因为toString方法可能会返回一个更加用户友好的名称。 此方法主要用于特殊情况下,正确性取决于获取确切的名称,从发行版到发行版不会有所不同 。 返回:此枚举常量的名称

例如,如果您有两个枚举: DaysMyDays ,其中SUNDAY是常用值,则在您比较两个string时,SUNDAY将返回true,请参阅http:// ideone中的工作示例。 com / U1Bmcw 。

 /* Name of the class has to be "Main" only if the class is public. */ class Ideone { public static enum Day{SUNDAY, MONDAY, TUESDAY}; public static enum MyDays{SUNDAY}; public static void main (String[] args) throws java.lang.Exception { MyDays m = Ideone.MyDays.SUNDAY; Day d = Ideone.Day.SUNDAY; System.out.println(d.name() == m.name()); } }