我们能用java设计一个真正的单例类吗?

我们能用java设计一个真正的单例类吗?,java,design-patterns,reflection,singleton,Java,Design Patterns,Reflection,Singleton,是否存在可以完全阻止创建多个对象的单例设计 问这个问题时要记住,在Java中,我们可以使用序列化、反序列化和反射来重新创建“单例对象”。是的,Java 5引入了枚举,它不允许通过序列化等方式创建其他实例 在Java 5+中创建单例的标准方法是使用一个常量枚举。是的,Java 5引入了枚举,它不允许通过序列化等方式创建其他实例 在Java 5+中创建单例的标准方法是使用一个常量枚举。您可以使用枚举创建单例模式,这是在Java中实现单例的最佳方式,但请记住,每个类加载器只有一个单例 可序列化单例

是否存在可以完全阻止创建多个对象的单例设计


问这个问题时要记住,在Java中,我们可以使用序列化、反序列化和反射来重新创建“单例对象”。

是的,Java 5引入了枚举,它不允许通过序列化等方式创建其他实例


在Java 5+中创建单例的标准方法是使用一个常量枚举。

是的,Java 5引入了枚举,它不允许通过序列化等方式创建其他实例


在Java 5+中创建单例的标准方法是使用一个常量枚举。

您可以使用枚举创建单例模式,这是在Java中实现单例的最佳方式,但请记住,每个类加载器只有一个单例

可序列化单例

 public enum Elvis {
       INSTANCE;
       private final String[] favoriteSongs =
           { "ABC", "DEF" };
       public void printFavorites() {
           System.out.println(Arrays.toString(favoriteSongs));
       }
   }

您可以使用enum生成singleton模式,这是在java中实现singleton的最佳方式,但请记住,每个类加载器只有一个singleton

可序列化单例

 public enum Elvis {
       INSTANCE;
       private final String[] favoriteSongs =
           { "ABC", "DEF" };
       public void printFavorites() {
           System.out.println(Arrays.toString(favoriteSongs));
       }
   }

可能是或否,这取决于您要采取的步骤和您想采取的案例

纯粹在JVM中,我认为不是。不同类加载器加载的资源被认为是不同的。因此,无论您进行了什么检查,您的单个
Foo.class
文件都可以由不同的类加载器加载,并且将创建静态对象的两个实例。他们提到的静态变量会有所不同,因此其中一个无法看到另一个已经创建

但是,如果您愿意使用外部资源(例如,本地文件系统上的文件,假设您确实可以写入目录),那么这是可能的。这是假设外部系统具有compare和set或其他同步语义,否则可能存在竞争条件,这可能导致两个潜在实例都看到另一个实例没有运行,然后启动


后一种情况可能与此相关,这取决于您为何如此确定第二个实例不存在。如果是因为它可能会损坏某些外部资源,请将约束条件放在该资源本身上。

可能是或否,这取决于您要执行的步骤和考虑的情况

纯粹在JVM中,我认为不是。不同类加载器加载的资源被认为是不同的。因此,无论您进行了什么检查,您的单个
Foo.class
文件都可以由不同的类加载器加载,并且将创建静态对象的两个实例。他们提到的静态变量会有所不同,因此其中一个无法看到另一个已经创建

但是,如果您愿意使用外部资源(例如,本地文件系统上的文件,假设您确实可以写入目录),那么这是可能的。这是假设外部系统具有compare和set或其他同步语义,否则可能存在竞争条件,这可能导致两个潜在实例都看到另一个实例没有运行,然后启动


后一种情况可能与此相关,这取决于您为何如此确定第二个实例不存在。如果这是因为它可能会损坏某些外部资源,请对该资源本身进行约束。

是的,我们可以设计一个真正的单例类(它也是线程安全的)。
但每个单例类都只是给定类装入器中的单例,
在运行时不在整个JVM中

有关更多详细信息,请查看这些相关问题


是的,我们可以设计一个真正的单例类(它也是线程安全的)。
但每个单例类都只是给定类装入器中的单例,
在运行时不在整个JVM中

有关更多详细信息,请查看这些相关问题


单元素枚举类型是实现单元素枚举的最佳方式

它将免费提供系列化机械,并提供 铁一般的保证,即使面对复杂的
序列化或反射攻击。

单元素枚举类型是实现单元素枚举的最佳方式

它将免费提供系列化机械,并提供 铁一般的保证,即使面对复杂的
序列化或反射攻击。

是的,您可以在java中创建一个真正的单例类

例如:

public class Foo {

private Foo f = null;
//More Variables

private Foo(){    //Constructor
}

public static Foo getInstance() {
if (f == null) { //f is the instance of the class Foo.
f = new Foo();
} 
return f; 
}

public void display() {
System.out.println("Display");
}

//...More Methods
}

In order to call, you may use it as:
Foo.getInstance().display();

每次调用getInstance(),它只会在应用程序的生命周期中生成一个Foo类的实例。

是的,您可以在java中生成一个真正的单例类

例如:

public class Foo {

private Foo f = null;
//More Variables

private Foo(){    //Constructor
}

public static Foo getInstance() {
if (f == null) { //f is the instance of the class Foo.
f = new Foo();
} 
return f; 
}

public void display() {
System.out.println("Display");
}

//...More Methods
}

In order to call, you may use it as:
Foo.getInstance().display();

每次调用getInstance(),在应用程序的生命周期内,它只会生成一个类Foo的实例。

在此之前,您可以定义
真正的
?通过“真正”,我的意思是在应用程序范围内只能创建一个实例。在此之前,您可以通过“真正”定义
真正的
,我的意思是,在应用程序作用域中只能创建一个实例。使用不同的类加载器,您仍然可以创建多个…@assylias使用不同的类加载器,然后讨论不同的类(从JVM的角度),因此,对于给定的类,它仍然是单例的。类似于使用扳手作为锤子。对于不同的类加载器,您仍然可以创建多个…@assylias,使用不同的类加载器,您将谈论不同的类(从JVM的角度),因此,对于给定的类,它仍然是单例的。类似于使用扳手作为锤子。