public class MySingleton{
private static final MySingleton INSTANCE = new MySingleton();
private MySingleton(){}
public static getInstance(){
return INSTANCE;
}
}
这是实现Singleton的正确方法吗?如果是,则最终关键字的必要性是什么?
答案 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)
还有另外一个方面,似乎没有人在讨论:使单例实例最终不会使它不可变。如果该类具有其他实例变量,则这些变量将成为单例的一部分,并且可以通过常用方法进行修改。