今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。
我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。
为什么我应该在日常编程中使用enum ?
今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。
我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。
为什么我应该在日常编程中使用enum ?
当前回答
在我的经验中,我看到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.
总之,如果您所表示的数据随着时间的推移是非常静态的,并且有有限数量的依赖项,则枚举是很好的选择。但是如果数据变化很大并且有很多依赖关系,那么就需要一些在编译时不检查的动态的东西(比如数据库表)。
其他回答
基于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
枚举就像类。与类一样,它也有方法和属性。
不同阶级的区别是: 1. 枚举常量是public, static, final。 2. 枚举不能用于创建对象,也不能扩展其他类。但是它可以实现接口。
不管别人怎么说…在我曾经工作过的一个旧项目中,实体(独立应用程序)之间的大量通信使用代表一个小集合的整数。用静态方法将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写入日志
希望这能有所帮助。
Enum继承Object类和抽象类Enum的所有方法。所以你可以使用它的方法来反射、多线程、序列化、可比性等等。如果你只是声明一个静态常量而不是Enum,你就不能。除此之外,Enum的值也可以传递给DAO层。
下面是要演示的示例程序。
public enum State {
Start("1"),
Wait("1"),
Notify("2"),
NotifyAll("3"),
Run("4"),
SystemInatilize("5"),
VendorInatilize("6"),
test,
FrameworkInatilize("7");
public static State getState(String value) {
return State.Wait;
}
private String value;
State test;
private State(String value) {
this.value = value;
}
private State() {
}
public String getValue() {
return value;
}
public void setCurrentState(State currentState) {
test = currentState;
}
public boolean isNotify() {
return this.equals(Notify);
}
}
public class EnumTest {
State test;
public void setCurrentState(State currentState) {
test = currentState;
}
public State getCurrentState() {
return test;
}
public static void main(String[] args) {
System.out.println(State.test);
System.out.println(State.FrameworkInatilize);
EnumTest test=new EnumTest();
test.setCurrentState(State.Notify);
test. stateSwitch();
}
public void stateSwitch() {
switch (getCurrentState()) {
case Notify:
System.out.println("Notify");
System.out.println(test.isNotify());
break;
default:
break;
}
}
}
在我的经验中,我看到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.
总之,如果您所表示的数据随着时间的推移是非常静态的,并且有有限数量的依赖项,则枚举是很好的选择。但是如果数据变化很大并且有很多依赖关系,那么就需要一些在编译时不检查的动态的东西(比如数据库表)。