将Java中的枚举定义为类与C/C++中仅作为常量集合的枚举相比,有哪些优点?
你可以免费获得编译时检查的有效值。使用
public static int OPTION_ONE = 0;
public static int OPTION_TWO = 1;
不能保证
void selectOption(int option) {
...
}
这将仅接受0或1作为参数值。使用枚举可以保证此功能。此外,这会导致更具自我记录性的代码,因为您可以使用代码完成功能查看所有枚举值。
类型安全是一个原因。
另一个,我认为更为重要的,是你可以在Java中为枚举值附加元数据。例如,你可以使用枚举来定义webservice的合法操作集,然后附加请求类型和数据类的元数据:
AddItem(HttpMethod.POST, ProductEntry.class),
主要问题在于int常量和int枚举类型不是类型安全的。可以传递任何int值。在C/C++中,可以这样做:
enum A { one, two, three };
enum B { beef, chicken, pork } b = beef;
void func(A a) { ... }
func((A)b);
readResolve()
不是什么大问题。对于有限数量实例的类,我经常这样做。有时,枚举可以简化这些类的定义,有时则不然。用正确的工具来完成工作。 - finnwpublic enum Elvis {
INSTANCE
}
将枚举作为引用类型,可以包含一组固定的常量,这导致了高效的Map实现,例如EnumMap和Set实现,例如EnumSet(JDK类)。
从EnumMap的javadoc中:
专门为枚举类型键设计的Map实现。在创建映射时,所有枚举映射中的键都必须来自指定的单个枚举类型,该类型明确或隐式地指定。枚举映射在内部表示为数组。此表示非常紧凑和高效。
EnumMap将Map的丰富性和类型安全性与数组的速度相结合(Effective Java)。
枚举是一种独立的类型 - 你不能使用不存在的枚举,或者放入其他类似的常量。此外,你可以对它们进行枚举,以使代码更加简洁。
使用静态常量可能会导致维护上的噩梦 - 特别是如果它们分散在各处。
唯一的真正优势是它可以在switch
语句中使用。枚举能够完成的所有其他事情都可以使用普通的类来完成,该类具有私有构造函数,其实例反过来被声明为该类的public static final
字段(类型安全模式)。枚举的另一个优点显然是它使代码比使用普通类更简洁。
但是,如果我没有记错,在C++(或者是C#?)中,您可以在switch
语句中使用String
。因此,与C ++相比,Java中枚举的这种优势微不足道。但是,同样的事情也被提议用于Java 7,不确定是否会实现。