【问题标题】:Make an enum INSTANCE private将枚举实例设为私有
【发布时间】:2011-03-11 14:30:33
【问题描述】:

我正在使用这样的枚举单例模式:

public enum LicenseLoader implements ClientLicense {
    INSTANCE;

    /**
     * @return an instance of ClientLicense
     */
    public static ClientLicense getInstance() {
        return (ClientLicense)INSTANCE;
    }

   ...rest of code

}

现在我想返回接口并隐藏我们实际上正在使用枚举的事实。我希望客户端使用 getInstance() 而不是 LicenseLoader.INSTANCE,因为有一天我可能会决定在必要时使用不同的模式。

是否可以将 INSTANCE 设为枚举私有?

【问题讨论】:

    标签: java singleton enums private


    【解决方案1】:

    如何创建一个public interfaceprivate enum 那个implements 表示接口,并带有一个单例INSTANCE 常量?

    所以,像这样(为简洁起见,都在一个类中):

    public class PrivateEnum {
    
        public interface Worker {
            void doSomething();
        }
    
        static private enum Elvis implements Worker {
            INSTANCE;
            @Override public void doSomething() {
                System.out.println("Thank you! Thank you very much!");
            }
        }
    
        public Worker getWorker() {
            return Elvis.INSTANCE;
        }
    }
    

    这样,您不会暴露Elvis.INSTANCE(甚至根本不会暴露enum Elvis),而是使用interface 来定义您的功能,隐藏所有实现细节。

    【讨论】:

    • 这非常有效,它允许我将 Worker 包设为私有,也允许我获取一些我想对外界保密但在包上下文中可用的东西。
    • enum 实例仍然可用,正如我解释的那样。
    【解决方案2】:

    所有enum 常量都可以访问。例如通过反序列化或enum-specific 反射方法。

    与往常一样,我强烈建议避免使用单例。

    【讨论】:

    • 你给出的建议很糟糕。 “即使面对复杂的序列化或反射攻击,枚举单例模式也提供了针对多次实例化的铁定保证。” (有效的 Java - Joshua Bloch)
    • 不,我没有给你不好的建议。
    • @Tom:你是什么意思它“仍然可用”(评论我的回答)? enum 上的 private 可访问性修饰符不是铁定的(例如 setAccessible 攻击),但每个 class 都是如此,而不仅仅是 enum
    • @polygenelubricants 您可以使用ObjectInputStream.readObject 读取实例。还有Enum.valueOf等方法。
    • @polygenelubricants 为我工作! public class Priv { private enum En { THING } } class Pub { public static void main(String[] args) throws Exception { Class clazz = Class.forName("Priv$En"); System.err.println(Enum.valueOf(clazz, "THING")); } }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多