了解Java中的枚举

什么是java枚举? 他们是如何工作的? 我在哪里可以使用它们以及如何使用
我可以不在应用程序中使用枚举,或者它们是如此强大以至于使用它们比忽略它们更好吗?

Java 5+中的枚举基本上是具有预定义实例集的类。 它们旨在替代整数常量的集合。 它们最好是常数,因为它们可以强制类型安全。

所以代替:

public class Suit { public final static int SPADES = 1; public final static int CLUBS = 2 public final static int HEARTS = 3; public final static int DIAMONDS = 4; } 

你有:

 public enum Suit { SPADES, CLUBS, HEARTS, DIAMONDS } 

优点是:

  1. 类型安全。 您可以将函数参数,返回类型,类成员或局部变量声明为特定的枚举类型,编译器将强制执行类型安全;
  2. 枚举基本上是类。 他们可以实现接口,具有行为等。

类型安全是一个问题,因为在第一个示例中,这些是有效的语句:

 int i = Suit.DIAMONDS * Suit.CLUBS; 

或者你可以将11传递给期待西装的function。 你不能用类型安全的枚举来做到这一点。

您可以使用Suit的类来提供类型安全性,这是Java 5之前的解决方案.Josh Bloch(在Effective Java中 ,这是Java程序员imho 必读的内容)提升了类型安全的枚举模式,该模式成为Java 5+枚举。 它上面有相当数量的样板和人们不倾向于满足的一些极端情况,例如序列化没有调用构造函数,并且确保只有一个实例必须覆盖readResolve()方法。

例如:

 public enum CardColour { RED, BLACK } public enum Suit { SPADES(CardColour.BLACK), CLUBS(CardColour.BLACK), HEARTS(CardColour.RED), DIAMONDS(CardColour.RED); private final CardColour colour; Suit(CardColour colour) { this.colour = colour; } public CardColour getColour() { return colour; } } 

编辑: Sun 介绍了类型安全的枚举 。

至于接口,它们确实补充了枚举而不是替代。 就像你可以说Suit是一个界面,你有这个:

 public interface Suit { CardColour getColour(); } 

问题是你可以去定义300种不同的套装,你也可以多次定义黑桃。 枚举的另一个优点是(尽管加载了极端情况)是每个枚举值只有一个实例。 通常,这被称为具有规范值 ,这意味着此等式成立:

 a.equals(b) == b.equals(a) == (a == b) 

对于所有a,b,它们是特定枚举的实例。 这意味着不是写作:

 if (card.getSuit().equals(Suit.SPADES)) { ... } 

你可以写:

 if (card.getSuit() == Suit.SPADES) { ... } 

这更快,通常更容易阅读。 如果您正在比较不同类型的枚举,说它们可能不相等,那么IDE通常会给您反馈,这可能是一种有用且早期的错误检查forms。

想想Enum如下

 public class MyEnum { // Object instantiated at declaration public static final MyEnum ONE = new MyEnum(); public static final MyEnum TWO = new MyEnum(); public static final MyEnum THREE = new MyEnum(); // Notice a private constructor // There is no way outside MyEnum class call it private MyEnum() { ... } } 

因此,作为枚举的MyEnum将是

 public enum MyEnum { ONE, TWO, THREE; } 

两者都相似

问候,

Sun的枚举文档可能是最好的解释。 当然,你可以不用它们,因为Java程序员肯定会在Java 1.5发布之前完成。 通常在1.5之前的Java版本中使用常量来完成同样的事情。 但枚举是一个很好的方便。

如果情况没有出现,那么你不需要它们。

它们允许您拥有一组定义明确的东西,例如,如果您想表示您可能拥有的物质状态:

 enum MatterState { Solid, Liquid, Gas; } 

他们在多大程度上击败了使用对象来表示集合的旧式,其中一些是:

  • 您可以在switch语句中使用它们。
  • 更少的代码。
  • 内置于/来自字符串。

要添加一些额外的信息以便更多地了解它,最好从变量的概念及其值开始。 我现在肯定你,每个变量都有一个声明的类型(比如Java基元类型)。 每种类型都有自己的相应值。 例如,具有char类型的变量可以接受所有单个字符作为其值。 因此,当您想要声明变量可以接受所有字符常量集时,它非常有用。 例如,对于aCharToStopProgram变量,所有字符常量都是可接受且有意义的:

 char aCharToStopProgram = getUserInput(); 

但是,如果您的值有限,我的意思是您的变量的值域限制为特殊值。 例如,您有userChoice,它保留系统多项选择问题的值。 所以只是’a’,’b’,’c’,’d’才有意义。 您不希望在程序代码的其他部分(或任何其他原因)为此变量分配无意义的值,例如’s’。 现在对我们的变量使用char原语类型是真的,它可以接受任何字符常量,如下所示。

 char userChoice = getUserChoice(); 

在这种情况下,Java提供了枚举类型。 这意味着通过enum关键字,您可以定义一个具有有限和固定实例的新类,这些实例是调用命名值(您无法创建新对象)。 例如:

 enum MultipleChoiceAnswer { A, B, C, D }; 

要么

 public enum MultipleChoiceAnswer { A('a'), B('b'), C('c'), D('d'); private char choice; private MultipleChoiceAnswer(char choice) { this.choice = choice; } public String getChoice() { return choice; } } 

因此,您可以使用自己的类型定义变量:

 MultipleChoiceAnswer userChoice = getUserChoice();//OR MultipleChoiceAnswer.A 

从我的解释来看,枚举更多的是为了可读性而不是其他任何东西。 它们基本上用于替换像1-6这样的值,使用更多描述性名称,如[Happy,Sad,Angry等],只要您需要使用一小组变量来描述您期望的解决方案,就应该使用它们。