|
1 |
| -# 比较java中枚举成员是用“==”还是equals() |
2 |
| - |
3 |
| -## 问题 |
4 |
| -java枚举被编译成带有私有构造器和一堆public的静态成员的类。当比较枚举中的两个成员时,经常使用.equals()方法,例如 |
5 |
| - public useEnums(SomeEnum a) |
6 |
| - { |
7 |
| - if(a.equals(SomeEnum.SOME_ENUM_VALUE)) |
8 |
| - { |
9 |
| - ... |
10 |
| - } |
11 |
| - ... |
12 |
| - } |
13 |
| -然而,偶然间使用“==”代替equals方法 |
14 |
| - public useEnums2(SomeEnum a) |
15 |
| - { |
16 |
| - if(a == SomeEnum.SOME_ENUM_VALUE) |
17 |
| - { |
18 |
| - ... |
19 |
| - } |
20 |
| - ... |
21 |
| - } |
22 |
| -应该使用哪个呢? |
23 |
| -## 解答 |
24 |
| -### 回答1 |
25 |
| -技术上来说,都是对的,如果你看了equals的源码,它简单地遵从“==” ,然而我一般使用“==” 因为它对于空指针,比较安全 |
26 |
| -### 回答2 |
27 |
| -#### 能在枚举时使用用“==”吗? |
28 |
| - |
29 |
| -可以,枚举值有小型实例控制,允许你用“==”去比较实例,在文档中有说明: |
30 |
| - |
31 |
| -JLS 8.9 枚举 |
32 |
| -一个枚举类型除了定义的那些枚举常量外没有其他实例了。 |
33 |
| -试图明确地说明一种枚举类型是会导致编译期异常。在枚举中final clone方法确保枚举常量从不会被克隆,而且序列化机制会确保从不会因为反序列化而创造复制的实例。枚举类型的反射实例化也是被禁止的。总之,以上内容确保了除了定义的枚举常量之外,没有枚举类型实例。 |
34 |
| - |
35 |
| -因为每个枚举常量只有一个实例,所以如果在比较两个参考值,至少有一个涉及到枚举常量时,允许使用“==”代替equals()。(equals()方法在枚举类中是一个final方法,在参数和返回结果时,很少调用父类的equals()方法,因此是一种恒等的比较。) |
36 |
| - |
37 |
| -这足够强力地支持Josh的建议,如果你坚持使用单例模式,最好的方法是用枚举类型强化单例属性(见Effective Java第二版中的第三条:用私有构造器或者枚举类型强化Singleton属性,或者单例模式的线程安全 |
38 |
| ->http://stackoverflow.com/questions/2912281/thread-safety-in-singleton/ ) |
39 |
| -
|
40 |
| -#### “==”和equals的区别 |
41 |
| -通常情况下,==并不是可以替换equals,然而在枚举中是可以的。它们之间有两个重要的不同: |
42 |
| - |
43 |
| - “==”从不会抛出空指针异常 |
44 |
| - |
45 |
| - |
46 |
| - enum Color { BLACK, WHITE }; |
47 |
| - |
48 |
| - Color nothing = null; |
49 |
| - |
50 |
| - if (nothing == Color.BLACK); // 正常运行 |
51 |
| - |
52 |
| - if (nothing.equals(Color.BLACK)); // 抛出空指 |
53 |
| - 针异常 |
54 |
| - |
55 |
| -在编译期,"=="会检查其类型的兼容性 |
56 |
| - |
57 |
| - enum Color { BLACK, WHITE }; |
58 |
| - enum Chiral { LEFT, RIGHT }; |
59 |
| - |
60 |
| - if (Color.BLACK.equals(Chiral.LEFT)); // 编译正常 |
61 |
| - if (Color.BLACK == Chiral.LEFT); // 无法编译,类型不兼容 |
62 |
| - |
63 |
| -#### 在适用时,“==”可以被使用吗 |
64 |
| - |
65 |
| -Bloch(effective java的作者)明确指出不可变类可以控制它们实例保证客户端“==”是可用的。枚举就被明确地证明了 |
66 |
| - |
67 |
| -考虑静态工厂方法代替构造器 |
68 |
| -它使得不可变的类可以确保不会存在两个相等的实例,即当且仅当a==b的时候才有a.equals(b)为true。如果类保证了这一点,它的客户端可以使用“==”操作符来代替equals(Object)方法,这样可以提升性能。枚举类型保证了这一点 |
69 |
| - |
70 |
| -总之,在枚举中使用“==”优势: |
71 |
| - |
72 |
| -- 能运行 |
73 |
| -- 更快 |
74 |
| -- 在运行期更安全 |
75 |
| -- 在编译期更安全 |
76 |
| - |
77 |
| -备注:强有力的反击了那些认为foo.equals(bar)比foo==bar更有可读性的人们。 |
78 |
| - |
79 |
| -原文地址: |
80 |
| -> http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals |
| 1 | +## 比较java枚举成员使用equal还是== |
| 2 | + |
| 3 | +### 问题 |
| 4 | +我知道Java枚举会被编译成一个包含私有构造参数和一堆静态方法的类,当去比较两个枚举的时候,总是使用equals()方法,例如: |
| 5 | +```java |
| 6 | +public useEnums(SomeEnum a) |
| 7 | +{ |
| 8 | + if(a.equals(SomeEnum.SOME_ENUM_VALUE)) |
| 9 | + { |
| 10 | + ... |
| 11 | + } |
| 12 | + ... |
| 13 | +} |
| 14 | +``` |
| 15 | +除此之外,我也可以使用 == 替代equals() 方法 |
| 16 | +```java |
| 17 | +public useEnums2(SomeEnum a) |
| 18 | +{ |
| 19 | + if(a == SomeEnum.SOME_ENUM_VALUE) |
| 20 | + { |
| 21 | + ... |
| 22 | + } |
| 23 | + ... |
| 24 | +} |
| 25 | +``` |
| 26 | +我有5年以上的java编程经验,并且我想我也懂得 == 和 equals() 之间的区别,但是我仍然觉得很困惑,哪一个操作符才是我该使用的。 |
| 27 | + |
| 28 | +### 答案 |
| 29 | + |
| 30 | +二者皆对,如果你看过枚举的源码,你会发现在源码中,equals也仅仅非常简单的 == 。 |
| 31 | +我使用 == ,因为无论如何,这个左值是可以为 null的 |
| 32 | + |
| 33 | + |
| 34 | +译者补充 java.lang.Enum 中Equals 代码: |
| 35 | +```java |
| 36 | +public final boolean equals(Object other) { |
| 37 | + return this==other; |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | + |
| 42 | +### 额外答案 |
| 43 | +#### 能在枚举中使用 == 进行判断? |
| 44 | +答案是肯定的,因为枚举有着严格的实例化控制,所以你可以用 == 去做比较符,这个用法,在官方文档中也有明确的说明。 |
| 45 | + |
| 46 | +>JLS 8.9 Enums |
| 47 | +>An enum type has no instances other than those defined by its enum constants. |
| 48 | +>It is a compile-time error to attempt to explicitly instantiate an enum type. The final clone method in Enum >ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures >that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types >is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by >the enum constants. |
| 49 | +>Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the >equals method when comparing two object references if it is known that at least one of them refers to an enum ?>constant. (The equals method in Enum is a final method that merely invokes super.equals on its argument and ?>returns the result, thus performing an identity comparison.) |
| 50 | +
|
| 51 | +#### 什么时候 == 和 equals 不一样? |
| 52 | +As a reminder, it needs to be said that generally, == is NOT a viable alternative to equals. When it is, however (such as with enum), there are two important differences to consider: |
| 53 | +通常来说 == 不是一个 equals的一个备选方案,无论如何有2个重要的不同处需要考虑: |
| 54 | + |
| 55 | +##### == 不会抛出 NullPointerException |
| 56 | +```java |
| 57 | +enum Color { BLACK, WHITE }; |
| 58 | + |
| 59 | +Color nothing = null; |
| 60 | +if (nothing == Color.BLACK); // runs fine |
| 61 | +if (nothing.equals(Color.BLACK)); // throws NullPointerException |
| 62 | +``` |
| 63 | +##### == 在编译期检测类型兼容性 |
| 64 | +```java |
| 65 | +enum Color { BLACK, WHITE }; |
| 66 | +enum Chiral { LEFT, RIGHT }; |
| 67 | + |
| 68 | +if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine |
| 69 | +if (Color.BLACK == Chiral.LEFT); // DOESN'T COMPILE!!! Incompatible types! |
| 70 | +``` |
| 71 | + |
| 72 | +#### 什么时候使用 == ? |
| 73 | +Bloch specifically mentions that immutable classes that have proper control over their instances can guarantee to their clients that == is usable. enum is specifically mentioned to exemplify. |
| 74 | +具体来说,那些提供恰当实例控制的不可变类能够保证 == 是可用的,枚举刚好符合这个条件。 |
| 75 | + |
| 76 | +> Item 1: Consider static factory methods instead of constructors |
| 77 | +> [...] it allows an immutable class to make the guarantee that no two equal instances exist: a.equals(b) if and only if a==b. If a class makes this guarantee, then its clients can use the == operator instead of the equals(Object) method, which may result in improved performance. Enum types provide this guarantee. |
| 78 | +
|
| 79 | +总而言之,在枚举比较上使用 == , 因为: |
| 80 | +1. 能正常工作 |
| 81 | +2. 更快 |
| 82 | +3. 运行时是安全的 |
| 83 | +4. 编译期也是安全的 |
| 84 | + |
| 85 | +stackoverlfow链接:http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals |
0 commit comments