关于Java:EnUM equals() 和==

Enum equals() and ==

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
enum Drill{
        ATTENTION("Attention!"), AT_EASE("At Ease");    
        private String str;
        private Drill(String str){
            this.str = str;
        }
        public String toString(){
            return str;
        }
    }
public class EnumExample {
    public static void main(String[] args) {
            Drill d1= Drill.valueOf("ATTENTION");
            Drill d2= Drill.valueOf("ATTENTION");
            **System.out.println(d1.equals(d2));//TRUE
            System.out.println(d1==d2);//TRUE**
            System.out.println(Drill.ATTENTION.equals(Drill.valueOf("ATTENTION")));
            System.out.println(Drill.ATTENTION.equals(Drill.AT_EASE));//FALSE
            System.out.println(Drill.ATTENTION==Drill.valueOf("ATTENTION"));//TRUE
            System.out.println(Drill.ATTENTION==Drill.AT_EASE);//FALSE
}
}

使用==和equals()时的枚举行为似乎相同。据我所知,==只需检查参考文献。因此,d1==d2应为假。有人能解释这种行为为什么是真的吗?


==应该可以很好地处理枚举,因为给定枚举项没有多个引用;只有一个引用。EnUM类型的Java语言规范部分,8.9表示它们是隐式的静态的和最终的,因此只能创建一次。


您正在比较枚举常量。这意味着对于每个枚举常量,都会创建一个实例。

这个

1
2
3
4
enum Drill{
    ATTENTION("Attention!"), AT_EASE("At Ease");
    ...
}

或多或少等同于

1
2
3
4
5
final class Drill {
    public static final Drill ATTENTION = new Drill("Attention!") {};
    public static final Drill AT_EASE = new Drill("At Ease") {};
    ...
}

valueOf

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Returns the enum constant of this type with the specified
* name.
* The string must match exactly an identifier used to declare
* an enum constant in this type.  (Extraneous whitespace
* characters are not permitted.)
*
* @return the enum constant with the specified name
* @throws IllegalArgumentException if this enum type has no
* constant with the specified name
*/

public static E valueOf(String name);

返回变量引用的实例值,该变量的名称等于指定的String值。

所以

1
Drill.valueOf("ATTENTION") == Drill.ATTENTION

每次调用valueOf时,使用该String值。


文件中的Enum Types

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

Because they are constants, the names of an enum type's fields are in uppercase letters.

1
2
Drill d1= Drill.valueOf("ATTENTION"); // ATTENTION
Drill d2= Drill.valueOf("ATTENTION"); // ATTENTION

因此,d1 == d2d1.equals(d2),因为它们指的是相同的常量值,即Drill.ATTENTION


在枚举中,所有项都是单例的:它们只构造一次(为了在执行开始时简单化,主要是在需要时)。因此,它们遵循单例模式(可能是使用单例模式的唯一好理由之一)。

因此,在内存中,enum中的每个元素都有一个实例。

valueOf方法只是作为一个flyweight:JVM保留某种类型的字典并返回适当的枚举项实例。

另一方面,我认为使用equals方法仍然是明智的,因为这为程序员提供了在枚举项上定义相等分区的机会。(假设AB是相等的,但有一些不同的行为)。


JVM的组织方式使得不可能或实际上不可能实例化每个枚举常量的多个实例。http://docs.oracle.com/javase/tutorial/java/javaoo/enum.html

当调用valueof时,它只返回已经实例化的枚举常量。