简体   繁体   English

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

[英]What is the purpose of Enum class which was introduced in Java 5?

My suggestions: 我的建议:

1) either enum s exist only before compilation (like generics; but I've never heard anything about it whilst it's written everywhere that generics are being erased after compilation) 1) enum只在编译之前存在(比如泛型;但是我从来没有听过任何关于它的内容,而它在任何地方写的都是在编译后删除了泛型)

2) or Enum is a way to maintain backward compatibility in some way (but I don't see that way yet). 2)或Enum是一种以某种方式保持向后兼容性的方法(但我还没有看到这种方式)。

Any other suggestions? 还有其他建议吗? (btw, have you ever used it in your code?) (顺便问一下,你有没有在你的代码中使用它?)

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

In other words, there's a enum keyword and Enum class. 换句话说,有一个enum关键字和Enum类。 They both appeared in Java 5. The question: why do we need both? 它们都出现在Java 5中。问题是:为什么我们需要两者?

The second question: why Enum became a part of the API? 第二个问题:为什么Enum成为API的一部分?

From the Java Tutorials : 来自Java教程

You should use enum types any time you need to represent a fixed set of constants. 您需要在需要表示一组固定常量时使用枚举类型。 That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on. 这包括自然枚举类型,例如太阳系中的行星和数据集,您可以在编译时知道所有可能的值 - 例如,菜单上的选项,命令行标志等。

Enums are extremely useful, and yes, I have used them plenty of times in my code. 枚举非常有用,是的,我在代码中使用了很多次。


Edit: 编辑:

...there's a enum keyword and Enum class. ...有一个enum关键字和Enum类。 They both appeared in Java 5. The question: why do we need both? 它们都出现在Java 5中。问题是:为什么我们需要两者?

This question is analogous to asking "there's a class keyword and an Object class. Why do we need both?" 这个问题类似于问“有一个class关键字和一个Object类。为什么我们需要两个?”

In both cases, the keywords are basically hints to the compiler; 在这两种情况下,关键字基本上都是编译器的提示; you could think of them as syntactic sugar that saves you keystrokes, and lets the compiler do less work (by not making it guess about what you're declaring). 您可以将它们视为语法糖,以节省您的击键次数,并让编译器减少工作量(通过不猜测您要声明的内容)。

See this q&a as well. 请参阅此q&a

...have you ever used it in your code? 你在代码中使用过它吗?

The answer is still "yes." 答案仍然是“是的”。 In particular, Enum#valueOf() is a static method useful for parsing strings: 特别是, Enum#valueOf()是一个用于解析字符串的静态方法:

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

but of course this works, too: 但当然这也有效:

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

Enums exist to represent type-safe enumerations (much better than using int constants for the same thing). 存在枚举以表示类型安全的枚举(比使用int常量更好)。

If you're asking what the purpose of the Enum class itself is - it's to act as the superclass for the user-defined enum s. 如果你问的是Enum类本身的目的是什么 - 它是作为用户定义的enum的超类。 Each enum is compiled into a class that extends Enum with the appropriate generic parameter (ie itself). 每个枚举都被编译成一个类,该类使用适当的泛型参数(即自身)扩展Enum

Why is this done via syntactic sugar rather than simple subclassing? 为什么这是通过语法糖而不是简单的子类来完成的? For one, it enforces the specific syntax that enums have (static instances forming the enum members). 首先,它强制执行枚举所具有的特定语法(构成枚举成员的静态实例)。 Another reason might be that the generic manipulations required to subclass Enum<E extends Enum<E>> would be very confusing to developers who had never seen any generics before. 另一个原因可能是, Enum<E extends Enum<E>>所需的通用操作对于之前从未见过任何泛型的开发人员来说会非常困惑。 By hiding this complexity behind a new keyword, developers wouldn't have to decipher it themselves. 通过将这种复杂性隐藏在新关键字后面,开发人员不必自己解密它。 Finally, the keyword implies that it's a special construct that shouldn't really be treated the same as a normal class. 最后,关键字意味着它是一个特殊的构造,不应该像普通类一样对待它。

In my humble opinion, the main thing enums are good for is type safety. 在我的拙见中,enums的主要内容是类型安全。

Suppose you have a function which can be called with some option that has a fixed set of possibilities. 假设你有一个函数可以使用一些具有固定可能性的选项调用。 Say, "sale" or "return". 说,“出售”或“返回”。 A really bad solution would be to pass in a string, like: 一个非常糟糕的解决方案是传入一个字符串,如:

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

One big catch to this method is if someone were to try calling it with "Sale" or "sail". 这种方法的一大难题是如果有人尝试用“Sale”或“sail”来调用它。 Unless the program verifies that only valid parameters are passed in, misspellings could give mysterious bugs. 除非程序验证只传入有效参数,否则拼写错误可能会产生神秘的错误。

So okay, many programmers created constants for this: 好吧,很多程序员为此创建了常量:

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

That's much better, but it still has problems. 那好多了,但还是有问题。 Suppose we have two parameters: 假设我们有两个参数:

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

Now someone gets confused and calls doTransaction(FOREIGN, SALE) . 现在有人感到困惑,并调用doTransaction(FOREIGN, SALE) This will compile successfully, pass any validity tests within the program, and give totally incorrect results. 这将成功编译,通过程序中的任何有效性测试,并给出完全不正确的结果。 Because if you didn't catch it, the parameters are in the wrong order. 因为如果你没有捕获它,参数的顺序是错误的。

Enums solve this problem. 枚举解决了这个问题。 If instead you write 相反,如果你写

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

Now if someone tries to write, doTransaction(Locale.FOREIGN, SaleType.SALE) , they get a compile-time error, and immediately know that they have the parameters wrong. 现在,如果有人尝试编写doTransaction(Locale.FOREIGN, SaleType.SALE) ,它们会收到编译时错误,并立即知道它们的参数错误。

Enum was added so the functionality provided by enum is visable and documented. 添加了枚举,因此枚举提供的功能是可见的并记录在案。 What would be gained by hiding this class? 隐藏这门课会得到什么?

generics are not erased after compilation. 编译后,泛型不会被删除。

Not sure why an Enum class would be needed for backward compatibility. 不确定为什么向后兼容需要Enum类。

I have used the class to read what Enums do and in code to check for Enum type, valueOf etc. 我已经使用该类来阅读Enums所做的事情,并在代码中检查Enum类型,valueOf等。

Ironically, this question was posted just before yours. 具有讽刺意味的是,这个问题就在你的面前发布了。 It shows examples of using the class. 它显示了使用该类的示例。 Checking if a class is java.lang.Enum 检查类是否为java.lang.Enum

either enums exist only before compilation 要么枚举只在编译之前存在

This is true, if you're talking about the enum syntax in the declaration, as opposed to the class syntax. 如果您在声明中讨论enum语法而不是class语法,那么确实如此。 At the bytecode level, Java enums are classes just like any other class. 在字节码级别,Java枚举就像任何其他类一样。 The enum semantics are basically implemented by the Java compiler. 枚举语义基本上由Java编译器实现。

在他们的Javadoc上查看完整的推理列表

I am not sure about #2. 我不确定#2。 But I use Enums all the time in Java. 但我一直在Java中使用Enums。 Instead of doing 而不是做

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

You can do 你可以做

public enum Option{one, two}

This is much cleaner because now you can declare all your funcitons like so: 这样更干净,因为现在您可以像这样声明所有功能:

public void doSomething(Option o);

Where as the old way, you had to do public void doSomething(int i) and I could have passed any integer. 作为旧的方式,你必须做public void doSomething(int i) ,我可以传递任何整数。 Therefore, the parameter was never check to make sure it is a valid option. 因此,从不检查参数以确保它是有效选项。 This allows for much cleaner code at compile time and run time. 这允许在编译时和运行时更清晰的代码。

I also use Enum a lot when it gets to doing variations of the same things. 当它做同样事情的变化时,我也经常使用Enum。 Let's say we have a sort attribute. 假设我们有一个sort属性。

You can do something like this which is very clean and much BETTER than case statements. 你可以做类似这样的事情,它比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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM