详解Java枚举为什么是单例模式的最佳选择
作者:不一样的科技宅 时间:2022-07-16 20:42:47
前言
单例模式,是工作中比较常见的一种设计模式,通常有两种实现方式,懒汉式和饿汉式。但是这两种实现方式存在一些问题。懒汉式需要在多线程环境下使用同步锁机制来保证只有一个实例被创建,这会影响程序的性能。而饿汉式在类加载时就创建实例,会导致程序在启动时变慢,同时也无法延迟实例的创建,这可能会浪费系统资源。所以今天介绍一下,为什么枚举是实现单例模式的最佳选择。
示例代码
public enum Singleton {
INSTANCE;
// 添加需要的实例变量和方法
private int count = 0;
public void incrementCount() {
count++;
}
public int getCount() {
return count;
}
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
singleton.incrementCount();
System.out.println(singleton.getCount()); // 输出 1
Singleton anotherSingleton = Singleton.INSTANCE;
anotherSingleton.incrementCount();
System.out.println(anotherSingleton.getCount()); // 输出 2
System.out.println(singleton.getCount()); // 输出 2
}
}
在上面的示例中,Singleton 是一个枚举类型,其中声明了一个枚举常量 INSTANCE,它是单例模式的唯一实例。
该单例模式还可以拥有实例变量和方法,如上面的 count 实例变量和 incrementCount()、getCount() 方法。
通过运行上面的代码,我们可以看到 singleton 和 anotherSingleton 是同一个实例,因为它们都是通过 Singleton.INSTANCE 获取的,所以它们的计数器变量 count 是共享的,所以在 anotherSingleton 上调用 incrementCount() 方法后,singleton 上的 count 值也会被增加。
有哪些优点?
线程安全
使用枚举实现单例模式是线程安全的。在多线程环境中,多个线程可以同时访问单例对象,但是由于枚举的特殊性质,只有一个实例对象被创建,所以不会出现线程安全问题。
序列化安全
使用枚举实现单例模式可以避免序列化和反序列化的问题。在 Java 中,当一个类被序列化并在另一个 JVM 中反序列化时,它会创建一个新的对象。如果使用枚举实现单例模式,则不需要担心这个问题,因为枚举实例是在加载枚举类型时由 JVM 创建的,并且它们是全局可访问的,因此不会出现创建多个实例的情况。
防止反射攻击
使用枚举实现单例模式可以防止反射攻击。在 Java 中,反射机制可以通过 Class 类来获取对象的构造函数并创建新的对象。如果使用枚举实现单例模式,则可以避免这种攻击,因为枚举类型的构造函数是私有的,不能通过反射来调用。
简单明了可读性强
使用枚举实现单例模式可以使代码更加简洁明了。枚举类型本身就是单例的,因此不需要编写任何特殊的代码来实现单例模式。并且具有有意义的名称和明确定义的值,这可以减少代码量和提高代码的可读性。
来源:https://juejin.cn/post/7229660119658512441
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java数组的定义与使用
![](https://img.aspxhome.com/file/2023/6/94336_0s.png)
C# 使用WPF 用MediaElement控件实现视频循环播放
Android手机卫士之设置密码对话框
![](https://img.aspxhome.com/file/2023/2/100652_0s.jpg)
mybatis-plus排除非表中字段的操作
C#中datagridview使用tooltip控件显示单元格内容的方法
一小时迅速入门Mybatis之初识篇
![](https://img.aspxhome.com/file/2023/2/132212_0s.jpg)
Java编程实现从尾到头打印链表代码实例
设置Myeclipse中的代码格式化、注释模板及保存时自动格式化
![](https://img.aspxhome.com/file/2023/4/120504_0s.png)
Java Web开发环境配置详解
![](https://img.aspxhome.com/file/2023/1/66971_0s.png)
Android基于ImageView绘制的开关按钮效果示例
![](https://img.aspxhome.com/file/2023/5/126705_0s.png)
java二叉树面试题详解
![](https://img.aspxhome.com/file/2023/6/63016_0s.png)
sharding-jdbc5.0.0实现分表实践
使用递归实现数组求和示例分享
Netty与NIO超详细讲解
![](https://img.aspxhome.com/file/2023/2/65362_0s.png)
Spring Boot配置AOP打印日志的全过程
详解C# 泛型中的数据类型判定与转换
![](https://img.aspxhome.com/file/2023/2/80082_0s.png)
详解MyBatis XML配置解析
![](https://img.aspxhome.com/file/2023/7/59887_0s.png)
C++ 中const修饰虚函数实例详解
C# 使用HttpClient模拟请求的案例
![](https://img.aspxhome.com/file/2023/7/91297_0s.jpg)