【问题标题】:How to call methods within Java Singleton enum constructor?如何在 Java Singleton 枚举构造函数中调用方法?
【发布时间】:2019-04-18 03:10:05
【问题描述】:

我的示例枚举 Singleton 类是:

public class Test{

    public enum MyClass{

        INSTANCE;

        private static String name = "Hello";

        MyClass() {
            test();
        }

        private static void test(){
            name = name + "World";
            System.out.println(name);
        }
    }

    public static void main(String a[]){

        MyClass m1 = MyClass.INSTANCE; 

    }
}

获得的输出:nullWorld
预期输出:HelloWorld

在main()中,如果

MyClass m1 = MyClass.INSTANCE;

被替换为

MyClass.INSTANCE.test();

那么,正如预期的那样,输出是 HelloWorld。

这表明静态字段在构造函数完成执行之前不会被初始化。

问题:如何实现在构造函数中调用访问静态字段的方法的功能?

【问题讨论】:

  • @AadhiraiR 单例的全部意义在于拥有一个可以保持状态的单个实例 - 为什么在单例中需要一个静态变量?只需将其设为实例变量即可。
  • @Hulk,真的!我意识到了这一点,并且正在删除枚举单例类中的所有静态字段。

标签: java enums constructor singleton


【解决方案1】:

这是因为INSTANCE是在name之前声明的,所以它是在name初始化之前创建和初始化的。

这行得通:

public enum MyClass{
    INSTANCE;
    private static final String name = "Hello";

    MyClass() {
        test();
    }

    private static void test(){
        String name1 = name + "World";
        System.out.println(name1);
    }

【讨论】:

  • 为什么将name定为final会起作用? final static 变量是否在 static 变量之前初始化,即使它们是在之后声明的?
  • 我的要求是有一个不是最终的静态变量。我希望能够修改它。
  • 我知道 Josh Bloch 在他的 Effective Java 书中建议了这种方式来实现单例模式。但是,当这种方法不起作用时,应该回退到通过类实现制作单例的旧方法,在这种方法中,您可以在 INSTANCE 变量之前定义 name 变量,然后不将其保持为最终状态,但仍然可以获得预期的输出!是否有任何强制您必须仅通过枚举来实现单例?
  • @Aadhirai R 如果不是枚举,您可以在 INSTANCE 之前移动名称,那么它会起作用。
  • @Kartik 设置为final 改变了一些事情,因为变量现在是compile-time constant。这意味着编译器将test()name 的使用替换为name 的常量值。由于这发生在编译时,因此初始化顺序没有问题。
猜你喜欢
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多