在java中创建单例类的最佳/正确方法是什么?
我发现的实现之一是使用私有构造函数和getinstance()方法。
package singleton;
public class Singleton {
private static Singleton me;
private Singleton() {
}
public static Singleton getInstance() {
if (me == null) {
me = new Singleton();
}
return me;
}
}
但是在下面的测试用例中实现失败了吗
package singleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test {
/**
* @param args
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Singleton singleton1 = Singleton.getInstance();
System.out.println(singleton1);
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton2);
Constructor<Singleton> c = Singleton.class
.getDeclaredConstructor((Class<?>[]) null);
c.setAccessible(true);
System.out.println(c);
Singleton singleton3 = c.newInstance((Object[]) null);
System.out.println(singleton3);
if(singleton1 == singleton2){
System.out.println("Variable 1 and 2 referes same instance");
}else{
System.out.println("Variable 1 and 2 referes different instances");
}
if(singleton1 == singleton3){
System.out.println("Variable 1 and 3 referes same instance");
}else{
System.out.println("Variable 1 and 3 referes different instances");
}
}
}
如何解决?
谢谢您
7条答案
按热度按时间mspsb9vt1#
根据对你问题的评论:
我有一个属性文件,其中包含一些键-值对,这是整个应用程序所需要的,这就是为什么我要考虑一个单例类。这个类将从一个文件中加载属性并保存它,您可以从应用程序中的任何地方使用它
不要用单件。显然,您不需要一次性的延迟初始化(这就是单例的全部内容)。您需要一次性直接初始化。只需将其设置为静态并将其加载到静态初始值设定项中。
例如
bcs8qyzn2#
如果您使用反射来穿透封装,当您的类的行为以不正确的方式被改变时,您不应该感到惊讶。私人成员应该是班级的私人成员。通过使用反射来访问它们,您故意破坏了类的行为,结果是“复制单例”。
简而言之:不要那样做。
另外,您可以考虑在静态构造函数中创建singleton示例。静态构造函数是同步的,只运行一次。当前类包含一个竞争条件——如果两个独立的线程调用
getInstance()
当它以前没有被调用时,有可能会创建两个示例,其中一个是其中一个线程的独占示例,而另一个则成为将来的示例getInstance()
电话将返回。v2g6jxz63#
我将以下面的方式实现singleton。
从wikiepdia描述的singleton\u模式出发,使用initialization on demand holder习惯用法
此解决方案是线程安全的,不需要特殊的语言构造(即。
volatile
或者synchronized
```public final class LazySingleton {
private LazySingleton() {}
public static LazySingleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazySingleton INSTANCE = new LazySingleton();
}
private Object readResolve() {
return LazyHolder.INSTANCE;
}
}
liwlm1x94#
在java中创建单例类的最佳方法是使用枚举。
示例如下:
引发nosuchmethodexception是因为我们无法使用反射通过枚举“singleinstance”的私有构造函数创建它的另一个示例。
在序列化的情况下,枚举默认实现可序列化接口。
vmdwslir5#
我认为您可以检查构造函数中是否已经存在示例,如果存在则抛出异常
dy2hfwbg6#
uemypmqf7#
只需遵循单例模式类图,
singletonclass-singletonobject:singletonclass-singletonclass()+getobject():singletonclass
关键点,
私有构造函数
类的示例应该在类中
提供返回示例的函数
一些代码,