Java单例类中是否需要final关键字?

时间:2012-12-13 23:39:54

标签: java singleton

public class MySingleton{
  private static final MySingleton INSTANCE = new MySingleton();
  private MySingleton(){}
  public static getInstance(){
    return INSTANCE;
  }
}

这是实现Singleton的正确方法吗?如果是,则最终关键字的必要性是什么?

5 个答案:

答案 0 :(得分:2)

Final将确保实例在创建后不可更改。如果你只包括一个构造函数,而且没有setter,那就没什么大不了的了。没有人可以改变你的实例而你也没有改变它。

如果稍后更改了课程,请将其保留在那里并不是一个坏主意。不变性提供了一些优势(更容易序列化,保护人员改变背后的物体等)。

将不可变性放回去比把它拿出来更难。防御性地编写你的代码,这样以后就没有人能把它搞乱了。

答案 1 :(得分:2)

通常首选的方法是使用枚举

public enum MySingleton {
    INSTANCE;
}

在您的示例中,final关键字显示意图并将阻止重新分配(= bug),但并非绝对必要。

特别是,变量是静态的,不需要最终在多线程环境中安全发布。

答案 2 :(得分:1)

没有一种正确的方法可以在Java中实现单例模式,但是使用公共静态最终实例变量是一种很好的方法,前提是您不需要延迟加载并且可以承受单元测试的后果。

如果单元测试是一个问题而您仍然需要单例,请考虑使用依赖注入。这将允许您配置具有单例生命周期的普通实例。

final修饰符允许Java编译器和运行时进行良好的优化和线程安全决策。我会一直使用final这种单例声明。我甚至会说允许单例实例是可变的是一个糟糕的设计选择 - 因为客户端代码不再依赖于在进程的生命周期中看到相同的值。

可以使用可配置的工厂类来处理单元测试问题:

private static final MySingleton INSTANCE = MySingletonFactory.create();

......不会失去最终的好处。

答案 3 :(得分:0)

不是真的有必要。但是使用final它不能被单例类本身重置,这会强制执行一个真正的单例。 但是,由于单例是不好的做法,因此可以通过添加setInstance()方法使它们可用于单元测试。不好的人可以定义setInstance private,这样单元测试通过反射调用setInstance。

答案 4 :(得分:0)

还有另外一个方面,似乎没有人在讨论:使单例实例最终不会使它不可变。如果该类具有其他实例变量,则这些变量将成为单例的一部分,并且可以通过常用方法进行修改。