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(...)而是使用它,因为任何阅读我的代码的人都会摸不着头脑,以为我犯了一个错误.
Pet*_*ček 33
Dasblinkenlight的答案是我们迄今为止的最佳答案.在那里他说:
这样做的原因是Java编译器
Enum以这样的方式构造子类 ,它们最终调用Enum's单独的受保护构造函数,并将其传递给enum值的名称
在那里他们得到实习,因为他们是字符串常量.
但是,在JLS,8.9.2,Enum Body声明中,有这样的:
实际上,编译器可能通过在
Enum类型的默认构造函数中声明String和int参数来镜像enum类型.但是,这些参数未指定为"隐式声明",因为不同的编译器不需要就默认构造函数的形式达成一致.只有enum类型的编译器知道如何实例化enum常量; 其他编译器可以简单地依赖于类型的隐式声明public static字段enum(第8.9.3节),而不考虑这些字段的初始化方式.
(强调我的)
所以我们将调用构造函数,但我们不会以任何特定的方式执行它,我们可以在编译器中管理自己的构造函数.
因此,我完全有可能编写一个正确且符合JLS的Java编译器,它不会以某种方式实现名称,可能是因为没有将名称存储为文字.是的,它会故意以恶意破坏您的代码为目的,但这将是每个规范的正确行为.
每个理智的实现都会实现字符串.我认为假设这种行为是安全的.但是,这并不能保证,因此如果我在实际代码中看到这一点,即使在评论中对其进行了详细描述,我也会对它非常不满意.
请不要依赖这种未指定和特定于实现的行为.如果你真的,真的必须,为它写一个单元测试.并assert在代码中加入了许多解释.衡量你的方法是否真的会做任何事情.
在使用它们之前,请考虑手动循环这不能可靠地工作.看评论.enum成员的名称和intern()手动名称.这样,它将立即清楚你正在做什么.