Java 5 中引入的 Enum 类的目的是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4166663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the purpose of Enum class which was introduced in Java 5?
提问by Roman
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
s 只在编译之前存在(就像泛型一样;但我从来没有听说过它,虽然到处都写着泛型在编译后被擦除)
2) or Enum is a way to maintain backward compatibility in some way (but I don't see that way yet).
2) or 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
更新: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. They both appeared in Java 5. The question: why do we need both?
换句话说,有一个enum
关键字和Enum
类。它们都出现在 Java 5 中。问题是:为什么我们需要两者?
The second question: why Enum
became a part of the API?
第二个问题:为什么Enum
成为API的一部分?
回答by Matt Ball
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. They both appeared in Java 5. The question: why do we need both?
...有一个 enum 关键字和 Enum 类。它们都出现在 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&aas well.
也请参阅此问答。
...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");
回答by Andrzej Doyle
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. Each enum is compiled into a class that extends Enum
with the appropriate generic parameter (i.e. itself).
如果您问Enum
类本身的目的是什么- 它是作为用户定义的enum
s的超类。每个枚举都被编译成一个类,该类扩展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 veryconfusing to developers who had never seen any generics before. 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.
为什么这是通过语法糖而不是简单的子类来完成的?一方面,它强制执行枚举具有的特定语法(构成枚举成员的静态实例)。另一个原因可能是需要的子类的一般操作Enum<E extends Enum<E>>
是非常混乱,以之前的任何仿制药谁从来没有见过开发商。通过将这种复杂性隐藏在新关键字后面,开发人员不必自己破译它。最后,关键字暗示它是一个特殊的构造,不应该真正与普通类一样对待。
回答by Jay
In my humble opinion, the main thing enums are good for is type safety.
在我看来,枚举的主要好处是类型安全。
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". Unless the program verifies that only valid parameters are passed in, misspellings could give mysterious bugs.
这种方法的一个大问题是,如果有人尝试用“Sale”或“sail”来调用它。除非程序验证只传入了有效参数,否则拼写错误可能会产生神秘的错误。
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)
. 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.
现在有人感到困惑并打电话给doTransaction(FOREIGN, SALE)
。这将成功编译,通过程序中的任何有效性测试,并给出完全错误的结果。因为如果你没有抓住它,参数的顺序是错误的。
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)
,他们会得到一个编译时错误,并且立即知道他们的参数是错误的。
回答by Michael Borgwardt
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. At the bytecode level, Java enums are classes just like any other class. The enum semantics are basically implemented by the Java compiler.
这是真的,如果您谈论的enum
是声明中的语法,而不是class
语法。在字节码级别,Java 枚举就像任何其他类一样是类。枚举语义基本上是由 Java 编译器实现的。
回答by Peter Lawrey
Enum was added so the functionality provided by enum is visable and documented. What would be gained by hiding this class?
添加了 Enum 以便 enum 提供的功能可见并记录在案。隐藏这个类会得到什么?
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.
我已经使用该类来读取 Enum 的作用,并在代码中检查 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
回答by Spav
回答by Amir Raminfar
I am not sure about #2. But I use Enums all the time in Java. Instead of doing
我不确定#2。但是我一直在 Java 中使用枚举。而不是做
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. 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.
作为旧方法,您必须这样做,public void doSomething(int i)
而我可以传递任何整数。因此,永远不会检查该参数以确保它是一个有效的选项。这允许在编译时和运行时更清晰的代码。
I also use Enum a lot when it gets to doing variations of the same things. Let's say we have a sort attribute.
在处理相同事物的变化时,我也经常使用 Enum。假设我们有一个排序属性。
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;
}