在Java中将枚举用作单例的最佳方法是什么?


85

在SO问题上编写的内容基础上构建Java最佳单例实现-即关于使用枚举创建单例-之间的区别/优点/缺点(省略构造函数)

public enum Elvis {
    INSTANCE;
    private int age;

    public int getAge() {
        return age;
    }
}

然后打电话 Elvis.INSTANCE.getAge()

public enum Elvis {
    INSTANCE;
    private int age;

    public static int getAge() {
        return INSTANCE.age;
    }
}

然后打电话 Elvis.getAge()

Answers:


96

假设您要绑定到将使用给定对象的属性的东西-您可以非常轻松地传递Elvis.INSTANCE,但是您不能传递Elvis.class并期望它找到该属性(除非它经过故意编码才能找到类的静态属性)。

基本上,仅在需要实例时才使用单例模式。如果静态方法适合您,则只需使用这些方法,而不必理会枚举。


1
为什么不麻烦枚举?在Java5 +中,有没有更好的方法来做单子呢?
jontro 2011年

4
@jontro(重新)阅读答案;他说在必须有单身人士的情况下使用枚举,但如果可以使用静态方法,则应避免单身人士
Miserable Variable

一年多以前,我对此@MiserableVariable进行了评论。不能真正记住我所指的上下文。
jontro

没有回答问的问题
Thufir

2
@Thufir:它回答了“有什么区别”部分-似乎是OP最感兴趣的部分,因为答案被接受了。
乔恩·斯基特

69

一个很大的优势是当您的单例必须实现接口时。按照您的示例:

public enum Elvis implements HasAge {
    INSTANCE;
    private int age;

    @Override
    public int getAge() {
        return age;
    }
}

带有:

public interface HasAge {
    public int getAge();
}

它不能用静态方法完成...


1
可以使用静态方法完成... public static final HasAge INSTANCE = new HasAge(){private int age; @Override public int getAge(){返回年龄;}; ...所以我仍然想知道枚举方法的优缺点。我想如果您需要实现两个接口?
肖恩·阿德金森

9

(有状态的)单例通常用来假装不使用静态变量。如果您实际上没有使用公共静态变量,那么您将蒙骗更少的人。


8

我会选择最简单,最清晰的选项。这在某种程度上是主观的,但是如果您不知道什么是最清楚的,那就选择最短的选项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.