枚举名称是在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就是这样的:
实际上,编译器可能通过在
Enum
types的默认构造函数中声明String
和int
参数来镜像Enum
types。 但是,这些参数没有被指定为“隐式声明”,因为不同的编译器不需要就默认构造函数的forms达成一致 。 只有enum
types的编译器知道如何实例化enum
常量; 其他编译器可以简单地依赖enum
types(第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方法可能会返回一个更加用户友好的名称。 此方法主要用于特殊情况下,正确性取决于获取确切的名称,从发行版到发行版不会有所不同 。 返回:此枚举常量的名称
例如,如果您有两个枚举: Days
和MyDays
,其中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()); } }