今天我浏览了这个网站上的一些问题,我发现一个枚举被用于单例模式,据称线程安全的好处,这种解决方案。

我从来没用过枚举,而且我已经用Java编程好几年了。显然,他们改变了很多。现在他们甚至在自己内部完全支持OOP。

为什么我应该在日常编程中使用enum ?


当前回答

而不是做一堆const int声明

您可以将它们都分组在一个enum中

所以它们都是由它们所属的共同群体组织起来的

其他回答

我会使用枚举作为有用的映射工具,避免使用多个if-else 前提是实现了一些方法。

public enum Mapping {

    ONE("1"),
    TWO("2");

    private String label;

    private Mapping(String label){
        this.label = label;
    }

    public static Mapping by(String label) {

        for(Mapping m: values() {
            if(m.label.equals(label)) return m;
        }

        return null;
    }

}

因此by(String label)方法允许您通过非枚举获取枚举值。此外,还可以创建两个枚举之间的映射。还可以尝试“1对多”或“多对多”,除了“一对一”的默认关系

最后,enum是一个Java类。你可以在里面有main方法,这在需要马上对参数做一些映射操作时很有用。

从Java文档-

您应该在任何时候使用枚举类型 需要表示一个固定的集合 常量。包括自然enum 比如我们太阳系中的行星 你知道的系统和数据集 编译时所有可能的值 时间——例如,a上的选项 菜单、命令行标志等等。

一个常见的例子是用枚举类型替换一个类,用一组私有静态final int常量(常量数量合理)。基本上,如果你认为你在编译时知道“something”的所有可能值,你可以将其表示为枚举类型。比起带有常量的类,枚举提供了可读性和灵活性。

枚举类型几乎没有其他优点。它们总是特定枚举类的一个实例(因此出现了使用枚举作为单例的概念)。另一个优点是可以在switch-case语句中使用枚举作为类型。你也可以在枚举上使用toString()将它们打印为可读的字符串。

基于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)在Switch-case语句中作为常量使用。 Switch case不允许使用String对象作为case。枚举可以派上用场。更多:http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/

2)再次实现单例设计模式- Enum,来拯救。这里的用法:在Java中使用Enum作为单例的最佳方法是什么?

枚举以自记录的方式枚举一组固定的值。 它们使您的代码更显式,也更不容易出错。

为什么不使用String,或int,而不是Enum常量?

编译器不允许错别字,也不允许出值的修正 设置,因为枚举本身就是类型。后果: 你不需要写一个先决条件(或手册)来确保你的论点在有效范围内。 类型不变式是免费的。 枚举可以有行为,就像任何其他类一样。 无论如何,您可能需要类似数量的内存来使用string(这取决于Enum的复杂性)。

此外,Enum的每个实例都是一个类,您可以为其定义单独的行为。

另外,它们在创建实例时(当枚举被加载时)确保线程安全,这在简化单例模式中有很好的应用。

这篇博客说明了它的一些应用,比如解析器的状态机。