在Java 5中引入的Enum类的目的是什么?

时间:2010-11-12 16:16:45

标签: java enums

我的建议:

1)只有enum才能在编译之前存在(就像泛型;但是我从来没有听说过任何关于它的内容,而且它编写的所有内容都在编译后被删除)

2)或Enum是一种以某种方式保持向后兼容性的方法(但我还没有看到这种方式)。

还有其他建议吗? (顺便说一句,你有没有在你的代码中使用它?)

UPD:http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html

换句话说,有一个enum关键字和Enum类。它们都出现在Java 5中。问题是:为什么我们需要两者?

第二个问题:为什么Enum成为API的一部分?

8 个答案:

答案 0 :(得分:10)

来自the Java Tutorials

  

只要需要表示一组固定的常量,就应该使用枚举类型。这包括自然枚举类型,例如太阳系中的行星和数据集,您可以在编译时知道所有可能的值 - 例如,菜单上的选项,命令行标志等。

枚举非常有用,是的,我在代码中已经多次使用它们。


修改

...有一个enum关键字和Enum类。它们都出现在Java 5中。问题是:为什么我们都需要它们?

这个问题类似于询问“有class个关键字和Object类。为什么我们需要两个?”

在这两种情况下,关键字基本上都是对编译器的提示;您可以将它们视为语法糖,可以节省您的击键次数,并让编译器减少工作量(通过不猜测您要声明的内容)。

同样请参阅this q&a

...您是否曾在代码中使用过它?

答案仍然是“是的”。特别是,Enum#valueOf()是一个用于解析字符串的静态方法:

DayOfWeek d = Enum.valueOf(DayOfWeek.class, "TUESDAY");

但当然这也有效:

DayOfWeek d = DayOfWeek.valueOf("TUESDAY");

答案 1 :(得分:4)

存在用于表示类型安全枚举的枚举(比同一事物使用int常量要好得多。)

如果你问的是Enum类本身的目的是什么 - 它是作为用户定义的enum的超类。每个枚举都被编译成一个类,该类使用适当的通用参数(即自身)扩展Enum

为什么这是通过语法糖而不是简单的子类来完成的?首先,它强制执行枚举所具有的特定语法(构成枚举成员的静态实例)。另一个原因可能是,子类Enum<E extends Enum<E>>所需的通用操作对于以前从未见过任何泛型的开发人员而言非常非常。通过将这种复杂性隐藏在新关键字后面,开发人员不必自己解密它。最后,关键字暗示它是一个特殊的构造,不应该像普通类一样对待它。

答案 2 :(得分:4)

在我的拙见中,enums的主要内容是类型安全。

假设您有一个可以使用某些选项调用的函数,该函数具有一组固定的可能性。说,“出售”或“返回”。一个非常糟糕的解决方案是传入一个字符串,如:

public void doTransaction(String type)
{
  if (type.equals("sale"))
    ... do whatever ...
}

这种方法的一大难题是如果有人尝试用“Sale”或“sail”来调用它。除非程序验证只传入有效参数,否则拼写错误会给出神秘的错误。

好吧,许多程序员为此创建了常量:

public final static int SALE=1, RETURN=2;
public void doTransaction(int type)
{
  if (type==SALE)
  ... do whatever ...
}

那好多了,但仍有问题。假设我们有两个参数:

public final static int SALE=1, RETURN=2;
public final static int DOMESTIC=1, FOREIGN=2;
public void doTransaction(int type, int locale)
{
  if (type==SALE && locale==DOMESTIC)
  ... etc ...
}

现在有人感到困惑并打电话给doTransaction(FOREIGN, SALE)。这将成功编译,通过程序中的任何有效性测试,并给出完全不正确的结果。因为如果你没有捕获它,参数的顺序是错误的。

枚举解决了这个问题。相反,如果你写了

enum SaleType {SALE, RETURN};
enum Locale {DOMESTIC, FOREIGN};
public void doTransaction(SaleType type, Locale locale)
... etc ...

现在,如果有人试图编写doTransaction(Locale.FOREIGN, SaleType.SALE),他们会收到编译时错误,并立即知道他们的参数错误。

答案 3 :(得分:1)

添加了枚举,因此枚举提供的功能是可见的并记录在案。隐藏这个课会得到什么?

编译后,

泛型不会被删除。

不确定为什么向后兼容需要Enum类。

我已经使用该类来阅读Enums所做的事情,并在代码中检查Enum类型,valueOf等。

具有讽刺意味的是,这个问题就在你的面前发布了。它显示了使用该类的示例。 Checking if a class is java.lang.Enum

答案 4 :(得分:1)

  

之前只有枚举存在   汇编

如果您在声明中讨论enum语法而不是class语法,那么确实如此。在字节码级别,Java枚举就像任何其他类一样。枚举语义基本上由Java编译器实现。

答案 5 :(得分:0)

答案 6 :(得分:0)

查看Javadoc

的完整推理列表

答案 7 :(得分:0)

我不确定#2。但我一直在Java中使用Enums。而不是做

public static final int OPTION_ONE = 1;
public static final int OPTION_TWO = 2;

你可以做到

public enum Option{one, two}

这个更干净,因为现在你可以像这样声明你所有的功能:

public void doSomething(Option o);

旧的方式,你必须做public void doSomething(int i),我可以传递任何整数。因此,从不检查参数以确保它是有效选项。这允许在编译时和运行时更清晰的代码。

当它做同样事情的变化时,我也经常使用Enum。假设我们有一个sort属性。

你可以做类似这样的事情,它比case语句更干净,更好。

public enum Sort {
        Everyone {
            @Override
            List<Checkin> refreshList(Client client, Location location) throws IOException {
                return client.checkins().getList();
            }
        },
        NearBy {
            @Override
            List<Checkin> refreshList(Client client, Location location) throws IOException {
                return client.checkinsNear(location.getLatitude(), location.getLongitude()).getList();
            }
        }; // and any other sorts

        abstract List<Checkin> refreshList(Client client, Location location) throws IOException;
    }