如何使用枚举创建单例 class

How to create a singleton class using enum

我正在尝试在 Java 中创建一个单例 class。 Java5 及以上版本的最佳可用解决方案似乎是使用 enum。但我不确定如何使用 enum 将我的 class 转换为单例 class。以下是我的简化 class:

public class Employee { 
   private int id; 
   private String name; 
   public Employee() {} 
   public int getId() {
      return id; 
   }
   public void setId( int id ) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   public void setName( String name ) {
      this.name = name; 
   }
}

当我在网上搜索答案时,我发现了以下代码:

public enum EasySingleton{
   INSTANCE;
}

但是我的 class 变量和方法在哪里?我不确定如何实施。我知道我们可以为 enum 提供方法,但是我的变量会去哪里呢?非常感谢对此的任何帮助。

P.S.: 请不要争论单例是邪恶的还是反模式的。我只是好奇如何使用 enum.

创建单例

class 和枚举之间的区别不是很大。我将第一行代码更改为 public enum 而不是 public class 并添加了您的实例名称。

public enum Employee { // changed "class" to "enum"

   INSTANCE; // added name of the (single) instance

   private int id; 
   private String name; 
   Employee() {} // removed "public"
   public int getId() {
      return id; 
   }
   public void setId( int id ) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   public void setName( String name ) {
      this.name = name; 
   }
}

请记住,如果您想在一个虚拟机中多次 运行 您的代码,单例、枚举实例、静态事物可能会在以后阻碍您。考虑在您的主 class 中创建一个 Employee 的实例,并将其传递给您的应用程序。

除此之外,枚举还有其他一些特殊功能:

  • 你不能extend另一个class(只能implements
  • 一些预定义的方法(如 static values()getName())可用
  • 构造函数只能是包私有的,或者是私有的

您的 "Employee" class 并不是真正应该是单例的东西,但这里是。

public enum Employee { 
   INSTANCE;

   private int id; 
   private String name; 

   private Employee() {}  //enum constructor must be private

   public int getId() {
      return id; 
   }

   public void setId( int id ) { 
      this.id = id; 
   } 

   public String getName() { 
      return name; 
   } 

   public void setName( String name ) {
      this.name = name; 
   }
}

那你可以做

Employee.INSTANCE.setName("Hello World!");

(在其他答案和评论中讨论了单例模式是否适合您的示例使用。我会假装回答具体问题,即使它实际上可能不相关。)

Bloch 的 Effective Java 对此进行了很好的讨论。参见第 17-18 页。我直接抄袭这个参考!

基本上,您可以使用枚举或私有构造函数来实施单例模式。 Bloch 更喜欢前者,尽管这种模式不太常见。

例如:

// Enum singleton
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

功能等同于 public 字段方法,并且无需更多样板即可进行序列化。而且永远只会有一个实例,即使面对棘手的反射或序列化访问也是如此。