与具有公共静态最终字段的类相比,Java enum的优点是什么?

时间:2021-08-07 23:24:26

I am very familiar with C# but starting to work more in Java. I expected to learn that enums in Java were basically equivalent to those in C# but apparently this is not the case. Initially I was excited to learn that Java enums could contain multiple pieces of data which seems very advantageous (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html). However, since then I have found a lot of features missing that are trivial in C#, such as the ability to easily assign an enum element a certain value, and consequently the ability to convert an integer to an enum without a decent amount of effort (i.e. Convert integer value to matching Java Enum).

我非常熟悉c#,但开始更多地使用Java。我本以为Java中的枚举与c#中的枚举基本相同,但显然不是这样的。最初,我很高兴地得知Java enums可以包含多个非常有利的数据片段(http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html)。然而,从那时起我发现很多琐碎的功能缺失在c#中,比如容易分配一个枚举元素一定值,因此可以把一个整数转换成一个枚举没有体面的工作(即整数值转换为匹配Java enum)。

So my question is this: is there any benefit to Java enums over a class with a bunch of public static final fields? Or does it just provide more compact syntax?

因此,我的问题是:Java枚举对于具有一系列公共静态最终字段的类有什么好处吗?还是仅仅提供更紧凑的语法?

EDIT: Let me be more clear. What is the benefit of Java enums over a class with a bunch of public static final fields of the same type? For example, in the planets example at the first link, what is the advantage of an enum over a class with these public constants:

编辑:让我更清楚一些。与具有一堆相同类型的公共静态最终字段的类相比,Java枚举的好处是什么?举个例子,在行星的例子中,在第一个连杆上,与具有这些公共常数的类相比,enum有什么好处呢?

public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);

As far as I can tell, casablanca's answer is the only one that satisfies this.

据我所知,卡萨布兰卡的答案是唯一能满足这个条件的。

15 个解决方案

#1


61  

Technically one could indeed view enums as a class with a bunch of typed constants, and this is in fact how enum constants are implemented internally. Using an enum however gives you useful methods (Enum javadoc) that you would otherwise have to implement yourself, such as Enum.valueOf.

从技术上讲,我们确实可以将枚举看作具有一堆类型常量的类,而这实际上就是枚举常量在内部实现的方式。然而,使用enum可以为您提供有用的方法(enum javadoc),否则您必须自己实现这些方法,比如Enum.valueOf。

#2


76  

  1. Type safety and value safety.
  2. 类型安全,重视安全。
  3. Guaranteed singleton.
  4. 保证单。
  5. Ability to define and override methods.
  6. 能够定义和覆盖方法。
  7. Ability to use values in switch statement case statements without qualification.
  8. 能够在没有限定条件的情况下使用switch语句case语句中的值。
  9. Built-in sequentialization of values via ordinal().
  10. 通过序号()内置的值序列化。
  11. Serialization by name not by value, which offers a degree of future-proofing.
  12. 按名称而不是值进行序列化,这提供了一定程度的未来验证。
  13. EnumSet and EnumMap classes.
  14. EnumSet和EnumMap类。

#3


67  

Nobody mentioned the ability to use them in switch statements; I'll throw that in as well.

没有人提到在switch语句中使用它们的能力;我也要把它写进去。

This allows arbitrarily complex enums to be used in a clean way without using instanceof, potentially confusing if sequences, or non-string/int switching values. The canonical example is a state machine.

这允许以一种干净的方式使用任意复杂的枚举,而不用instanceof,这可能会混淆序列或非字符串/int交换值。典型的例子是状态机。

#4


40  

There is less confusion. Take Font for instance. It has a constructor that takes the name of the Font you want, its size and its style (new Font(String, int, int)). To this day I cannot remember if style or size goes first. If Font had used an enum for all of its different styles (PLAIN, BOLD, ITALIC, BOLD_ITALIC), its constructor would look like Font(String, Style, int), preventing any confusion. Unfortunately, enums weren't around when the Font class was created, and since Java has to maintain reverse compatibility, we will always be plagued by this ambiguity.

有更少的混乱。比如字体。它有一个构造函数,该构造函数获取您想要的字体的名称、大小和样式(新字体(String, int, int))。直到今天,我都不记得是款式还是尺寸优先。如果字体对所有不同的样式(纯、粗体、斜体、粗体)都使用了enum,那么它的构造函数将看起来像字体(字符串、样式、int),以避免混淆。不幸的是,当创建字体类时,enums并没有出现,因为Java必须保持反向兼容性,所以我们总是会被这种模糊性所困扰。

Of course, this is just an argument for using an enum instead of public static final constants. Enums are also perfect for singletons and implementing default behavior while allowing for later customization (I.E. the strategy pattern). An example of the latter is java.nio.file's OpenOption and StandardOpenOption: if a developer wanted to create his own non-standard OpenOption, he could.

当然,这只是使用enum而不是公共静态最终常量的一个参数。Enums对于单例和实现默认行为也非常理想,同时允许稍后进行定制(即策略模式)。后者的一个例子是java.nio。file的OpenOption和StandardOpenOption:如果开发人员想创建自己的非标准OpenOption,他可以。

#5


37  

The primary advantage is type safety. With a set of constants, any value of the same intrinsic type could be used, introducing errors. With an enum only the applicable values can be used.

最主要的优点是类型安全。对于一组常量,可以使用任何相同的内部类型的值,从而引入错误。对于枚举,只能使用可应用的值。

For example

例如

public static final int SIZE_SMALL  = 1;
public static final int SIZE_MEDIUM = 2;
public static final int SIZE_LARGE  = 3;

public void setSize(int newSize) { ... }

obj.setSize(15); // Compiles but likely to fail later

vs

vs

public enum Size { SMALL, MEDIUM, LARGE };

public void setSize(Size s) { ... }

obj.setSize( ? ); // Can't even express the above example with an enum

#6


21  

There are many good answers here, but none mentiones that there are highly optimized implementations of the Collection API classes/interfaces specifically for enums:

这里有很多很好的答案,但是没有提到有针对枚举的集合API类/接口的高度优化实现:

These enum specific classes only accept Enum instances (the EnumMap only accept Enums only as keys), and whenever possible, they revert to compact representation and bit manipulation in their implementation.

这些枚举特定的类只接受枚举实例(枚举映射只接受枚举作为键),并且只要有可能,它们在实现中恢复为紧凑表示和位操作。

What does this mean?

这是什么意思?

If our Enum type has no more that 64 elements (most of real-life Enum examples will qualify for this), the implementations store the elements in a single long value, each Enum instance in question will be associated with a bit of this 64-bit long long. Adding an element to an EnumSet is simply just setting the proper bit to 1, removing it is just setting that bit to 0. Testing if an element is in the Set is just one bitmask test! Now you gotta love Enums for this!

如果我们的Enum类型不再包含64个元素(大多数实际的Enum示例都符合此要求),那么实现将元素存储在一个长值中,每个枚举实例都将与这个长64位的元素关联。向枚举集中添加一个元素仅仅是将适当的位设置为1,删除它只是将该位设置为0。测试一个元素是否在集合中只是一个位掩码测试!现在你要为这事高兴了!

#7


11  

The first benefit of enums, as you have already noticed, is syntax simplicity. But the main point of enums is to provide a well-known set of constants which, by default, form a range and help to perform more comprehensive code analysis through type & value safety checks.

正如您已经注意到的,枚举的第一个好处是语法简单。但是,enums的主要目的是提供一组众所周知的常量,这些常量在默认情况下会形成一个范围,并通过类型和值安全检查来帮助执行更全面的代码分析。

Those attributes of enums help both a programmer and a compiler. For example, let's say you see a function that accepts an integer. What that integer could mean? What kind of values can you pass in? You don't really know right away. But if you see a function that accepts enum, you know very well all possible values you can pass in.

枚举的这些属性对程序员和编译器都有帮助。例如,假设您看到一个接受整数的函数。这个整数是什么意思?你能传递什么样的价值观?你真的不知道。但是如果你看到一个接受enum的函数,你就会很清楚地知道你可以传入的所有可能的值。

For the compiler, enums help to determine a range of values and unless you assign special values to enum members, they are well ranges from 0 and up. This helps to automatically track down errors in the code through type safety checks and more. For example, compiler may warn you that you don't handle all possible enum values in your switch statement (i.e. when you don't have default case and handle only one out of N enum values). It also warns you when you convert an arbitrary integer into enum because enum's range of values is less than integer's and that in turn may trigger errors in the function that doesn't really accept an integer. Also, generating a jump table for the switch becomes easier when values are from 0 and up.

对于编译器来说,枚举有助于确定一个值范围,除非您为enum成员分配特殊的值,否则它们的范围很可能是0或以上。这有助于通过类型安全检查等方法自动跟踪代码中的错误。例如,编译器可能会警告您,您不能在switch语句中处理所有可能的enum值(例如,如果您没有默认情况,并且只处理N个enum值中的一个)。当您将任意整数转换为enum时,它还会警告您,因为enum的值范围小于integer,这反过来可能会触发函数中不真正接受整数的错误。此外,当值从0或以上时,为交换机生成跳转表变得更容易。

This is not only true for Java, but for other languages with a strict type-checking as well. C, C++, D, C# are good examples.

这不仅适用于Java,而且对于其他具有严格类型检查的语言也是如此。C, c++, D, c#是很好的例子。

#8


10  

example:

例子:

public class CurrencyDenom {
   public static final int PENNY = 1;
 public static final int NICKLE = 5;
 public static final int DIME = 10;
public static final int QUARTER = 25;}

Limitation of java Constants

java常数的限制

1) No Type-Safety: First of all it’s not type-safe; you can assign any valid int value to int e.g. 99 though there is no coin to represent that value.

1)没有类型安全:首先它不是类型安全的;你可以将任何有效的int值赋给int,例如99,尽管没有硬币来表示那个值。

2) No Meaningful Printing: printing value of any of these constant will print its numeric value instead of meaningful name of coin e.g. when you print NICKLE it will print "5" instead of "NICKLE"

2)没有意义的打印:任何一个常数的打印值将打印它的数值而不是有意义的硬币名称。

3) No namespace: to access the currencyDenom constant we need to prefix class name e.g. CurrencyDenom.PENNY instead of just using PENNY though this can also be achieved by using static import in JDK 1.5

3)没有命名空间:要访问currencyDenom常量,我们需要在类名前面加上前缀,例如,currencyDenom。PENNY不用PENNY,不过这也可以通过使用JDK 1.5中的静态导入来实现

Advantage of enum

利用枚举

1) Enums in Java are type-safe and has there own name-space. It means your enum will have a type for example "Currency" in below example and you can not assign any value other than specified in Enum Constants.

1) Java中的枚举类型安全,并且有自己的名称空间。这意味着您的enum将在下面的示例中有一个示例“Currency”类型,您不能指定枚举常量中指定的其他值。

public enum Currency {PENNY, NICKLE, DIME, QUARTER};

Currency coin = Currency.PENNY; coin = 1; //compilation error

货币的硬币= Currency.PENNY;硬币= 1;/ /编译错误

2) Enum in Java are reference type like class or interface and you can define constructor, methods and variables inside java Enum which makes it more powerful than Enum in C and C++ as shown in next example of Java Enum type.

Java中的Enum是类似类或接口的引用类型,您可以在Java Enum中定义构造函数、方法和变量,这使它比C和c++中的Enum更强大,如下面的Java Enum类型示例所示。

3) You can specify values of enum constants at the creation time as shown in below example: public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)}; But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.

3)可以在创建时指定enum常量的值,如下例所示:public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};但是要实现这一点,您需要定义一个成员变量和一个构造函数,因为PENNY(1)实际上在调用一个接受int值的构造函数,请参见下面的示例。

public enum Currency {
    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
    private int value;

    private Currency(int value) {
            this.value = value;
    }

};

};

refrence:http://javarevisited.blogspot.in/2011/08/enum-in-java-example-tutorial.html

具有:http://javarevisited.blogspot.in/2011/08/enum-in-java-example-tutorial.html

#9


4  

enum Benefits:

enum好处:

  1. Enums are type-safe, static fields are not
  2. 枚举是类型安全的,静态字段不是
  3. There is a finite number of values (it is not possible to pass non-existing enum value. If you have static class fields, you can make that mistake)
  4. 值的数量是有限的(不可能传递不存在的enum值。如果您有静态类字段,您可能会犯这个错误)
  5. Each enum can have multiple properties (fields/getters) assigned - encapsulation. Also some simple methods: YEAR.toSeconds() or similar. Compare: Colors.RED.getHex() with Colors.toHex(Colors.RED)
  6. 每个枚举可以有多个属性(字段/getter)分配——封装。还有一些简单的方法:YEAR.toSeconds()或类似的。比较:Colors.RED.getHex()与Colors.toHex(Colors.RED)

"such as the ability to easily assign an enum element a certain value"

“例如,能够轻松地为枚举元素赋值”

enum EnumX{
  VAL_1(1),
  VAL_200(200);
  public final int certainValue;
  private X(int certainValue){this.certainValue = certainValue;}
}

"and consequently the ability to convert an integer to an enum without a decent amount of effort" Add a method converting int to enum which does that. Just add static HashMap containing the mapping.

“因此,将一个整数转换为枚举而不需要大量的努力”,可以添加一个将int转换为enum的方法。只需添加包含映射的静态HashMap。

If you really want to convert ord=VAL_200.ordinal() back to val_200 just use: EnumX.values()[ord]

如果您真的想要将ord=VAL_200.ordinal()转换回val_200,只需使用:EnumX.values()[ord]

#10


4  

An enum is implictly final, with a private constructors, all its values are of the same type or a sub-type, you can obtain all its values using values(), gets its name() or ordinal() value or you can look up an enum by number or name.

enum是隐含的final,带有一个私有构造函数,所有的值都是相同类型或子类型,您可以使用values()获得所有值,获取它的名称()或序号()值,或者您可以通过数字或名称查找enum。

You can also define subclasses (even though notionally final, something you can't do any other way)

您还可以定义子类(即使在名义上是final的,也可以用其他任何方式)

enum Runner implements Runnable {
    HI {
       public void run() {
           System.out.println("Hello");
       }
    }, BYE {
       public void run() {
           System.out.println("Sayonara");
       }
       public String toString() {
           return "good-bye";
       }
    }
 }

 class MYRunner extends Runner // won't compile.

#11


3  

Another important difference is that java compiler treats static final fields of primitive types and String as literals. It means these constants become inline. It's similar to C/C++ #define preprocessor. see this SO question. This is not the case with enums.

另一个重要的区别是,java编译器将基元类型和字符串的静态最终字段视为文本。这意味着这些常量是内联的。它类似于C/ c++ #define预处理器。看到这样的问题。恩诺姆不是这样的。

#12


2  

You get compile time checking of valid values when you use an enum. Look at this question.

当您使用enum时,您将获得有效值的编译时检查。看看这个问题。

#13


2  

The biggest advantage is enum Singletons are easy to write and thread-safe :

最大的优点是enum单件易于编写和线程安全:

public enum EasySingleton{
    INSTANCE;
}

and

/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
     private volatile DoubleCheckedLockingSingleton INSTANCE;

     private DoubleCheckedLockingSingleton(){}

     public DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //double checking Singleton instance
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

both are similar and it handled Serialization by themselves by implementing

两者都是相似的,它通过实现自己来处理序列化。

//readResolve to prevent another instance of Singleton
    private Object readResolve(){
        return INSTANCE;
    }

more

更多的

#14


0  

I think an enum can't be final, because under the hood compiler generates subclasses for each enum entry.

我认为enum不能是最终的,因为在hood编译器下为每个enum条目生成子类。

More information From source

更多的信息从源

#15


0  

It's generally considered bad practice. The problem is that the constants are part of the public "interface" (for want of a better word) of the implementing class. This means that the implementing class is publishing all of these values to external classes even when they are only required internally. The constants proliferate throughout the code. An example is the SwingConstants interface in Swing, which is implemented by dozens of classes that all "re-export" all of its constants (even the ones that they don't use) as their own.
The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.
An enum may be a better approach. Or you could simply put the constants as public static fields in a class that cannot be instantiated. This allows another class to access them without polluting its own API.

这通常被认为是不好的做法。问题是这些常量是实现类的公共“接口”(为了更好地描述)的一部分。这意味着实现类将所有这些值发布到外部类中,即使这些值只在内部需要。常量在整个代码中增殖。Swing中的swingconstant接口就是一个例子,它是由几十个类实现的,这些类都将其所有的常量(甚至是不使用的常量)“重新导出”为它们自己的常量。常量接口模式是接口的糟糕使用。一个类在内部使用一些常量是一个实现细节。实现常量接口会导致这个实现细节泄露到类的导出API中。对于类的用户来说,类实现一个常量接口并不重要。事实上,它甚至可能让他们感到困惑。更糟糕的是,它代表了一个承诺:如果在将来的版本中修改了类,使它不再需要使用常量,那么它仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的名称空间都将被该接口中的常量污染。enum可能是一种更好的方法。或者,您可以将常量作为公共静态字段放在一个无法实例化的类中。这允许另一个类访问它们,而不会污染自己的API。

#1


61  

Technically one could indeed view enums as a class with a bunch of typed constants, and this is in fact how enum constants are implemented internally. Using an enum however gives you useful methods (Enum javadoc) that you would otherwise have to implement yourself, such as Enum.valueOf.

从技术上讲,我们确实可以将枚举看作具有一堆类型常量的类,而这实际上就是枚举常量在内部实现的方式。然而,使用enum可以为您提供有用的方法(enum javadoc),否则您必须自己实现这些方法,比如Enum.valueOf。

#2


76  

  1. Type safety and value safety.
  2. 类型安全,重视安全。
  3. Guaranteed singleton.
  4. 保证单。
  5. Ability to define and override methods.
  6. 能够定义和覆盖方法。
  7. Ability to use values in switch statement case statements without qualification.
  8. 能够在没有限定条件的情况下使用switch语句case语句中的值。
  9. Built-in sequentialization of values via ordinal().
  10. 通过序号()内置的值序列化。
  11. Serialization by name not by value, which offers a degree of future-proofing.
  12. 按名称而不是值进行序列化,这提供了一定程度的未来验证。
  13. EnumSet and EnumMap classes.
  14. EnumSet和EnumMap类。

#3


67  

Nobody mentioned the ability to use them in switch statements; I'll throw that in as well.

没有人提到在switch语句中使用它们的能力;我也要把它写进去。

This allows arbitrarily complex enums to be used in a clean way without using instanceof, potentially confusing if sequences, or non-string/int switching values. The canonical example is a state machine.

这允许以一种干净的方式使用任意复杂的枚举,而不用instanceof,这可能会混淆序列或非字符串/int交换值。典型的例子是状态机。

#4


40  

There is less confusion. Take Font for instance. It has a constructor that takes the name of the Font you want, its size and its style (new Font(String, int, int)). To this day I cannot remember if style or size goes first. If Font had used an enum for all of its different styles (PLAIN, BOLD, ITALIC, BOLD_ITALIC), its constructor would look like Font(String, Style, int), preventing any confusion. Unfortunately, enums weren't around when the Font class was created, and since Java has to maintain reverse compatibility, we will always be plagued by this ambiguity.

有更少的混乱。比如字体。它有一个构造函数,该构造函数获取您想要的字体的名称、大小和样式(新字体(String, int, int))。直到今天,我都不记得是款式还是尺寸优先。如果字体对所有不同的样式(纯、粗体、斜体、粗体)都使用了enum,那么它的构造函数将看起来像字体(字符串、样式、int),以避免混淆。不幸的是,当创建字体类时,enums并没有出现,因为Java必须保持反向兼容性,所以我们总是会被这种模糊性所困扰。

Of course, this is just an argument for using an enum instead of public static final constants. Enums are also perfect for singletons and implementing default behavior while allowing for later customization (I.E. the strategy pattern). An example of the latter is java.nio.file's OpenOption and StandardOpenOption: if a developer wanted to create his own non-standard OpenOption, he could.

当然,这只是使用enum而不是公共静态最终常量的一个参数。Enums对于单例和实现默认行为也非常理想,同时允许稍后进行定制(即策略模式)。后者的一个例子是java.nio。file的OpenOption和StandardOpenOption:如果开发人员想创建自己的非标准OpenOption,他可以。

#5


37  

The primary advantage is type safety. With a set of constants, any value of the same intrinsic type could be used, introducing errors. With an enum only the applicable values can be used.

最主要的优点是类型安全。对于一组常量,可以使用任何相同的内部类型的值,从而引入错误。对于枚举,只能使用可应用的值。

For example

例如

public static final int SIZE_SMALL  = 1;
public static final int SIZE_MEDIUM = 2;
public static final int SIZE_LARGE  = 3;

public void setSize(int newSize) { ... }

obj.setSize(15); // Compiles but likely to fail later

vs

vs

public enum Size { SMALL, MEDIUM, LARGE };

public void setSize(Size s) { ... }

obj.setSize( ? ); // Can't even express the above example with an enum

#6


21  

There are many good answers here, but none mentiones that there are highly optimized implementations of the Collection API classes/interfaces specifically for enums:

这里有很多很好的答案,但是没有提到有针对枚举的集合API类/接口的高度优化实现:

These enum specific classes only accept Enum instances (the EnumMap only accept Enums only as keys), and whenever possible, they revert to compact representation and bit manipulation in their implementation.

这些枚举特定的类只接受枚举实例(枚举映射只接受枚举作为键),并且只要有可能,它们在实现中恢复为紧凑表示和位操作。

What does this mean?

这是什么意思?

If our Enum type has no more that 64 elements (most of real-life Enum examples will qualify for this), the implementations store the elements in a single long value, each Enum instance in question will be associated with a bit of this 64-bit long long. Adding an element to an EnumSet is simply just setting the proper bit to 1, removing it is just setting that bit to 0. Testing if an element is in the Set is just one bitmask test! Now you gotta love Enums for this!

如果我们的Enum类型不再包含64个元素(大多数实际的Enum示例都符合此要求),那么实现将元素存储在一个长值中,每个枚举实例都将与这个长64位的元素关联。向枚举集中添加一个元素仅仅是将适当的位设置为1,删除它只是将该位设置为0。测试一个元素是否在集合中只是一个位掩码测试!现在你要为这事高兴了!

#7


11  

The first benefit of enums, as you have already noticed, is syntax simplicity. But the main point of enums is to provide a well-known set of constants which, by default, form a range and help to perform more comprehensive code analysis through type & value safety checks.

正如您已经注意到的,枚举的第一个好处是语法简单。但是,enums的主要目的是提供一组众所周知的常量,这些常量在默认情况下会形成一个范围,并通过类型和值安全检查来帮助执行更全面的代码分析。

Those attributes of enums help both a programmer and a compiler. For example, let's say you see a function that accepts an integer. What that integer could mean? What kind of values can you pass in? You don't really know right away. But if you see a function that accepts enum, you know very well all possible values you can pass in.

枚举的这些属性对程序员和编译器都有帮助。例如,假设您看到一个接受整数的函数。这个整数是什么意思?你能传递什么样的价值观?你真的不知道。但是如果你看到一个接受enum的函数,你就会很清楚地知道你可以传入的所有可能的值。

For the compiler, enums help to determine a range of values and unless you assign special values to enum members, they are well ranges from 0 and up. This helps to automatically track down errors in the code through type safety checks and more. For example, compiler may warn you that you don't handle all possible enum values in your switch statement (i.e. when you don't have default case and handle only one out of N enum values). It also warns you when you convert an arbitrary integer into enum because enum's range of values is less than integer's and that in turn may trigger errors in the function that doesn't really accept an integer. Also, generating a jump table for the switch becomes easier when values are from 0 and up.

对于编译器来说,枚举有助于确定一个值范围,除非您为enum成员分配特殊的值,否则它们的范围很可能是0或以上。这有助于通过类型安全检查等方法自动跟踪代码中的错误。例如,编译器可能会警告您,您不能在switch语句中处理所有可能的enum值(例如,如果您没有默认情况,并且只处理N个enum值中的一个)。当您将任意整数转换为enum时,它还会警告您,因为enum的值范围小于integer,这反过来可能会触发函数中不真正接受整数的错误。此外,当值从0或以上时,为交换机生成跳转表变得更容易。

This is not only true for Java, but for other languages with a strict type-checking as well. C, C++, D, C# are good examples.

这不仅适用于Java,而且对于其他具有严格类型检查的语言也是如此。C, c++, D, c#是很好的例子。

#8


10  

example:

例子:

public class CurrencyDenom {
   public static final int PENNY = 1;
 public static final int NICKLE = 5;
 public static final int DIME = 10;
public static final int QUARTER = 25;}

Limitation of java Constants

java常数的限制

1) No Type-Safety: First of all it’s not type-safe; you can assign any valid int value to int e.g. 99 though there is no coin to represent that value.

1)没有类型安全:首先它不是类型安全的;你可以将任何有效的int值赋给int,例如99,尽管没有硬币来表示那个值。

2) No Meaningful Printing: printing value of any of these constant will print its numeric value instead of meaningful name of coin e.g. when you print NICKLE it will print "5" instead of "NICKLE"

2)没有意义的打印:任何一个常数的打印值将打印它的数值而不是有意义的硬币名称。

3) No namespace: to access the currencyDenom constant we need to prefix class name e.g. CurrencyDenom.PENNY instead of just using PENNY though this can also be achieved by using static import in JDK 1.5

3)没有命名空间:要访问currencyDenom常量,我们需要在类名前面加上前缀,例如,currencyDenom。PENNY不用PENNY,不过这也可以通过使用JDK 1.5中的静态导入来实现

Advantage of enum

利用枚举

1) Enums in Java are type-safe and has there own name-space. It means your enum will have a type for example "Currency" in below example and you can not assign any value other than specified in Enum Constants.

1) Java中的枚举类型安全,并且有自己的名称空间。这意味着您的enum将在下面的示例中有一个示例“Currency”类型,您不能指定枚举常量中指定的其他值。

public enum Currency {PENNY, NICKLE, DIME, QUARTER};

Currency coin = Currency.PENNY; coin = 1; //compilation error

货币的硬币= Currency.PENNY;硬币= 1;/ /编译错误

2) Enum in Java are reference type like class or interface and you can define constructor, methods and variables inside java Enum which makes it more powerful than Enum in C and C++ as shown in next example of Java Enum type.

Java中的Enum是类似类或接口的引用类型,您可以在Java Enum中定义构造函数、方法和变量,这使它比C和c++中的Enum更强大,如下面的Java Enum类型示例所示。

3) You can specify values of enum constants at the creation time as shown in below example: public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)}; But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.

3)可以在创建时指定enum常量的值,如下例所示:public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};但是要实现这一点,您需要定义一个成员变量和一个构造函数,因为PENNY(1)实际上在调用一个接受int值的构造函数,请参见下面的示例。

public enum Currency {
    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
    private int value;

    private Currency(int value) {
            this.value = value;
    }

};

};

refrence:http://javarevisited.blogspot.in/2011/08/enum-in-java-example-tutorial.html

具有:http://javarevisited.blogspot.in/2011/08/enum-in-java-example-tutorial.html

#9


4  

enum Benefits:

enum好处:

  1. Enums are type-safe, static fields are not
  2. 枚举是类型安全的,静态字段不是
  3. There is a finite number of values (it is not possible to pass non-existing enum value. If you have static class fields, you can make that mistake)
  4. 值的数量是有限的(不可能传递不存在的enum值。如果您有静态类字段,您可能会犯这个错误)
  5. Each enum can have multiple properties (fields/getters) assigned - encapsulation. Also some simple methods: YEAR.toSeconds() or similar. Compare: Colors.RED.getHex() with Colors.toHex(Colors.RED)
  6. 每个枚举可以有多个属性(字段/getter)分配——封装。还有一些简单的方法:YEAR.toSeconds()或类似的。比较:Colors.RED.getHex()与Colors.toHex(Colors.RED)

"such as the ability to easily assign an enum element a certain value"

“例如,能够轻松地为枚举元素赋值”

enum EnumX{
  VAL_1(1),
  VAL_200(200);
  public final int certainValue;
  private X(int certainValue){this.certainValue = certainValue;}
}

"and consequently the ability to convert an integer to an enum without a decent amount of effort" Add a method converting int to enum which does that. Just add static HashMap containing the mapping.

“因此,将一个整数转换为枚举而不需要大量的努力”,可以添加一个将int转换为enum的方法。只需添加包含映射的静态HashMap。

If you really want to convert ord=VAL_200.ordinal() back to val_200 just use: EnumX.values()[ord]

如果您真的想要将ord=VAL_200.ordinal()转换回val_200,只需使用:EnumX.values()[ord]

#10


4  

An enum is implictly final, with a private constructors, all its values are of the same type or a sub-type, you can obtain all its values using values(), gets its name() or ordinal() value or you can look up an enum by number or name.

enum是隐含的final,带有一个私有构造函数,所有的值都是相同类型或子类型,您可以使用values()获得所有值,获取它的名称()或序号()值,或者您可以通过数字或名称查找enum。

You can also define subclasses (even though notionally final, something you can't do any other way)

您还可以定义子类(即使在名义上是final的,也可以用其他任何方式)

enum Runner implements Runnable {
    HI {
       public void run() {
           System.out.println("Hello");
       }
    }, BYE {
       public void run() {
           System.out.println("Sayonara");
       }
       public String toString() {
           return "good-bye";
       }
    }
 }

 class MYRunner extends Runner // won't compile.

#11


3  

Another important difference is that java compiler treats static final fields of primitive types and String as literals. It means these constants become inline. It's similar to C/C++ #define preprocessor. see this SO question. This is not the case with enums.

另一个重要的区别是,java编译器将基元类型和字符串的静态最终字段视为文本。这意味着这些常量是内联的。它类似于C/ c++ #define预处理器。看到这样的问题。恩诺姆不是这样的。

#12


2  

You get compile time checking of valid values when you use an enum. Look at this question.

当您使用enum时,您将获得有效值的编译时检查。看看这个问题。

#13


2  

The biggest advantage is enum Singletons are easy to write and thread-safe :

最大的优点是enum单件易于编写和线程安全:

public enum EasySingleton{
    INSTANCE;
}

and

/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
     private volatile DoubleCheckedLockingSingleton INSTANCE;

     private DoubleCheckedLockingSingleton(){}

     public DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //double checking Singleton instance
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

both are similar and it handled Serialization by themselves by implementing

两者都是相似的,它通过实现自己来处理序列化。

//readResolve to prevent another instance of Singleton
    private Object readResolve(){
        return INSTANCE;
    }

more

更多的

#14


0  

I think an enum can't be final, because under the hood compiler generates subclasses for each enum entry.

我认为enum不能是最终的,因为在hood编译器下为每个enum条目生成子类。

More information From source

更多的信息从源

#15


0  

It's generally considered bad practice. The problem is that the constants are part of the public "interface" (for want of a better word) of the implementing class. This means that the implementing class is publishing all of these values to external classes even when they are only required internally. The constants proliferate throughout the code. An example is the SwingConstants interface in Swing, which is implemented by dozens of classes that all "re-export" all of its constants (even the ones that they don't use) as their own.
The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.
An enum may be a better approach. Or you could simply put the constants as public static fields in a class that cannot be instantiated. This allows another class to access them without polluting its own API.

这通常被认为是不好的做法。问题是这些常量是实现类的公共“接口”(为了更好地描述)的一部分。这意味着实现类将所有这些值发布到外部类中,即使这些值只在内部需要。常量在整个代码中增殖。Swing中的swingconstant接口就是一个例子,它是由几十个类实现的,这些类都将其所有的常量(甚至是不使用的常量)“重新导出”为它们自己的常量。常量接口模式是接口的糟糕使用。一个类在内部使用一些常量是一个实现细节。实现常量接口会导致这个实现细节泄露到类的导出API中。对于类的用户来说,类实现一个常量接口并不重要。事实上,它甚至可能让他们感到困惑。更糟糕的是,它代表了一个承诺:如果在将来的版本中修改了类,使它不再需要使用常量,那么它仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的名称空间都将被该接口中的常量污染。enum可能是一种更好的方法。或者,您可以将常量作为公共静态字段放在一个无法实例化的类中。这允许另一个类访问它们,而不会污染自己的API。