今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。
我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。
为什么我应该在日常编程中使用enum ?
今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。
我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。
为什么我应该在日常编程中使用enum ?
当前回答
知道枚举就像其他具有常量字段和私有构造函数的类一样是有用的。
例如,
public enum Weekday
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
编译器按如下方式编译它;
class Weekday extends Enum
{
public static final Weekday MONDAY = new Weekday( "MONDAY", 0 );
public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );
private Weekday( String s, int i )
{
super( s, i );
}
// other methods...
}
其他回答
不管别人怎么说…在我曾经工作过的一个旧项目中,实体(独立应用程序)之间的大量通信使用代表一个小集合的整数。用静态方法将set声明为enum很有用,可以从value中获取enum object,反之亦然。代码看起来更干净,开关案例可用性和更容易写入日志。
enum ProtocolType {
TCP_IP (1, "Transmission Control Protocol"),
IP (2, "Internet Protocol"),
UDP (3, "User Datagram Protocol");
public int code;
public String name;
private ProtocolType(int code, String name) {
this.code = code;
this.name = name;
}
public static ProtocolType fromInt(int code) {
switch(code) {
case 1:
return TCP_IP;
case 2:
return IP;
case 3:
return UDP;
}
// we had some exception handling for this
// as the contract for these was between 2 independent applications
// liable to change between versions (mostly adding new stuff)
// but keeping it simple here.
return null;
}
}
使用ProtocolType.fromInt(2)从接收的值(例如1,2)创建enum对象 使用myEnumObj.name写入日志
希望这能有所帮助。
枚举?为什么要使用它?我认为当你使用它的时候会更容易理解。我也有同样的经历。
假设您有一个创建、删除、编辑和读取数据库操作。
现在如果你创建一个枚举作为一个操作:
public enum operation {
create("1")
delete("2")
edit("3")
read("4")
// You may have is methods here
public boolean isCreate() {
return this.equals(create);
}
// More methods like the above can be written
}
现在,你可以这样声明:
private operation currentOperation;
// And assign the value for it
currentOperation = operation.create
所以你可以在很多方面使用它。对于特定的事情使用enum总是好的,因为上面例子中的数据库操作可以通过检查currentOperation来控制。也许有人会说,这也可以用变量和整数值来实现。但我相信Enum更安全,更适合程序员。
另一件事:我认为每个程序员都喜欢布尔,不是吗?因为它只能存储两个值,两个特定的值。所以Enum可以被认为具有相同类型的功能,用户可以定义它将存储多少和什么类型的值,只是方式略有不同。:)
在我看来,你到目前为止的所有答案都是正确的,但根据我的经验,我想用几句话来表达:
如果希望编译器检查标识符值的有效性,请使用枚举。
否则,您可以像往常一样使用字符串(可能您为应用程序定义了一些“约定”),并且您将非常灵活……但是你不能在你的字符串上获得100%的安全,你只能在运行时意识到它们。
基于enum的单例
一个老问题的现代视角
这种方法通过利用Java的保证来实现单例,即任何enum值在Java程序中只实例化一次,并且enum为线程安全提供了隐式支持。由于Java枚举值是全局可访问的,因此它们可以作为单例使用。
public enum Singleton {
SINGLETON;
public void method() { }
}
这是如何工作的呢?好吧,代码的第二行可以被认为是这样的:
public final static Singleton SINGLETON = new Singleton();
我们得到了早期初始化的单例。
记住,因为这是一个枚举,你总是可以通过Singleton访问实例。单例也是:
Singleton s = Singleton.SINGLETON;
优势
To prevent creating other instances of singleton during deserialization use enum based singleton because serialization of enum is taken care by JVM. Enum serialization and deserialization work differently than for normal java objects. The only thing that gets serialized is the name of the enum value. During the deserialization process, the enum valueOf method is used with the deserialized name to get the desired instance. Enum based singleton allows to protect itself from reflection attacks. The enum type actually extends the java Enum class. The reason that reflection cannot be used to instantiate objects of enum type is that the java specification disallows and that rule is coded in the implementation of the newInstance method of the Constructor class, which is usually used for creating objects via reflection:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
Enum不应该被克隆,因为每个值必须只有一个实例。 所有单例实现中最简洁的代码。
缺点
The enum based singleton does not allow lazy initialization. If you changed your design and wanted to convert your singleton to multiton, enum would not allow this. The multiton pattern is used for the controlled creation of multiple instances, which it manages through the use of a map. Rather than having a single instance per application (e.g. the java.lang.Runtime) the multiton pattern instead ensures a single instance per key. Enum appears only in Java 5 so you can not use it in the prior version.
单例模式有几种实现方式,每一种都有优缺点。
急装单件 双重检查锁定单例 初始化-按需holder习语 基于enum的单例
详细的描述每个都太啰嗦了,所以我只是放了一个链接到一篇好文章-所有你想知道的关于Singleton
在我的经验中,我看到Enum的使用有时会导致系统很难改变。如果您正在为一组频繁更改的特定于域的值使用Enum,并且它有许多依赖于它的其他类和组件,那么您可能要考虑不使用Enum。
例如,一个交易系统使用Enum进行市场/交易所。市场有很多,几乎可以肯定的是,会有很多子系统需要进入这个市场列表。每当你想要一个新的市场添加到你的系统中,或者如果你想要删除一个市场,有可能太阳下的一切都将不得不重建和释放。
A better example would be something like a product category type. Let's say your software manages inventory for a department store. There are a lot of product categories, and many reasons why this list of categories could change. Managers may want to stock a new product line, get rid of other product lines, and possibly reorganize the categories from time to time. If you have to rebuild and redeploy all of your systems simply because users want to add a product category, then you've taken something that should be simple and fast (adding a category) and made it very difficult and slow.
总之,如果您所表示的数据随着时间的推移是非常静态的,并且有有限数量的依赖项,则枚举是很好的选择。但是如果数据变化很大并且有很多依赖关系,那么就需要一些在编译时不检查的动态的东西(比如数据库表)。