理解 Java 中的枚举 [英] Understanding Enums in Java

查看:28
本文介绍了理解 Java 中的枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

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

所以代替:

公共类西装{公共最终静态 int SPADES = 1;公共最终静态 int CLUBS = 2public final static int HEARTS = 3;公共最终静态 int DIAMONDS = 4;}

你有:

公共枚举套装{黑桃、俱乐部、红心、钻石}

优点是:

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

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

int i = Suit.DIAMONDS * Suit.CLUBS;

或者您可以将 11 传递给需要西装的函数.你不能用类型安全的枚举来做到这一点.

您可以使用 Suit 的类来提供类型安全,这是 Java 5 之前的解决方案.Josh Bloch(在 Effective Java,对于 Java 程序员来说必读,恕我直言)促进了成为 Java 5+ 枚举的类型安全枚举模式.它有相当多的样板文件和一些人们不倾向于满足的极端情况,例如序列化不调用构造函数并确保您只有一个实例,您必须覆盖 readResolve() 方法.

例如:

公共枚举 CardColour {红黑}公共枚举套装{黑桃(卡片颜色.黑色),俱乐部(卡片颜色.黑色),心(卡片颜色.红色),钻石(卡片颜色.红色);私人最终 CardColor 颜色;西装(CardColour 颜色){ this.colour = color;}public CardColour getColour() { 返回颜色;}}

Sun 有一个 类型安全枚举简介.

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

公共接口套装{CardColour getColour();}

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

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

对于作为特定 Enum 实例的所有 a, b.这意味着,而不是写:

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

你可以写:

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

这更快,通常更容易阅读.此外,如果您比较不同类型的枚举,IDE 通常会给您反馈,说它们不可能相等,这可能是一种有用的早期错误检查形式.

What are java enums? How do they work? Where could I used them and how?
Can I do without using enums in an app or are they so powerful that Its better to use them than ignore them?

解决方案

Enums in Java 5+ are basically classes that have a predefined set of instances. They are intended as a replacement for, say, a collection of integer constants. They are preferably to constants as they can enforce type safety.

So instead of:

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;
}

you have:

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

The advantages are:

  1. Type safety. You can declare a function argument, return type, class member or local variable to be a particular Enum type and the compiler will enforce type safety;
  2. Enums are basically classes. They can implement interfaces, have behaviour and so on.

The type safety is an issue because in the first example, these are valid statements:

int i = Suit.DIAMONDS * Suit.CLUBS;

or you can pass in 11 to a function expecting a suit. You can't do that with a typesafe enum.

You can use a class for Suit to provide type safety and this was the solution before Java 5. Josh Bloch (in Effective Java, which is a must read for Java programmers imho) promoted the typesafe enum pattern that became the Java 5+ enum. It has a fair amount of boilerplate on it and some corner cases that people didn't tend to cater for, such as serialization not calling a constructor and to ensure you only got one instance you had to override the readResolve() method.

For example:

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; }
}

Edit: Sun has an introduction to typesafe enums.

As for interfaces, they really complement enums rather than being an alternative. Like you could say that Suit is an interface and you'd have this:

public interface Suit {
  CardColour getColour();
}

The problem is that you could go and define 300 different suits and you could also define Spades several times. Another advantage of enums is (classloading corner cases notwithstanding) is that there is only one instance of each enum value. Typically this is referred to as having a canonical value, meaning this equality holds true:

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

for all a, b that are instances of a particular Enum. This means that instead of writing:

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

you can write:

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

which is quicker and typically easier to read. Plus IDEs will typically give you feedback if you're comparing enums of different types saying they can't possibly be equal, which can be a useful and early form of error-checking.

这篇关于理解 Java 中的枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆