本文目录导读:

我来为你提供一个完整的枚举单例案例,并详细解释其特点。
基础枚举单例
public enum Singleton {
INSTANCE;
private String config;
// 构造函数(枚举的构造器默认private)
Singleton() {
config = "默认配置";
// 可以在这里进行初始化操作
System.out.println("枚举单例被初始化");
}
public void doSomething() {
System.out.println("执行方法,配置为:" + config);
}
public void setConfig(String config) {
this.config = config;
}
}
测试类
public class EnumSingletonTest {
public static void main(String[] args) {
// 使用单例
Singleton singleton1 = Singleton.INSTANCE;
Singleton singleton2 = Singleton.INSTANCE;
System.out.println("是否为同一个实例: " + (singleton1 == singleton2));
System.out.println("hashCode 是否相同: " +
(singleton1.hashCode() == singleton2.hashCode()));
singleton1.doSomething();
// 修改配置
singleton1.setConfig("新的配置");
singleton2.doSomething(); // 验证配置已更新
// 测试多线程环境
testMultiThread();
}
private static void testMultiThread() {
Runnable task = () -> {
Singleton singleton = Singleton.INSTANCE;
System.out.println(Thread.currentThread().getName() +
" - 实例: " + singleton.hashCode());
};
for (int i = 0; i < 5; i++) {
new Thread(task, "线程-" + i).start();
}
}
}
带数据和方法的枚举单例
import java.io.*;
public enum DatabaseConnection {
INSTANCE;
// 模拟数据库连接池
private ConnectionPool pool;
private int connectionCount;
DatabaseConnection() {
System.out.println("初始化数据库连接池...");
pool = new ConnectionPool();
connectionCount = 0;
}
// 模拟连接池类
static class ConnectionPool {
void connect() {
System.out.println("创建数据库连接");
}
void disconnect() {
System.out.println("关闭数据库连接");
}
}
public synchronized void connect() {
connectionCount++;
pool.connect();
}
public synchronized void disconnect() {
if (connectionCount > 0) {
connectionCount--;
}
pool.disconnect();
}
public int getConnectionCount() {
return connectionCount;
}
public void showStatus() {
System.out.println("当前活跃连接数: " + connectionCount);
}
}
处理序列化的枚举单例
import java.io.*;
public enum SerializableSingleton implements Serializable {
INSTANCE;
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
// 枚举天然防止序列化破坏单例,无需实现readResolve()
// 但可以重写readResolve来确保反序列化后返回相同实例
private Object readResolve() {
return INSTANCE;
}
// 测试序列化行为
public static void main(String[] args) throws Exception {
SerializableSingleton instance = SerializableSingleton.INSTANCE;
instance.setData("测试数据");
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(instance);
oos.close();
// 反序列化
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
SerializableSingleton deserialized = (SerializableSingleton) ois.readObject();
ois.close();
System.out.println("序列化前后是否相同: " + (instance == deserialized));
System.out.println("反序列化后数据: " + deserialized.getData());
}
}
带延迟初始化的枚举单例(复杂场景)
public enum LazySingleton {
INSTANCE;
// 私有静态内部类用于延迟加载复杂资源
private enum ResourceHolder {
INSTANCE;
private ComplexResource resource;
ResourceHolder() {
System.out.println("延迟加载复杂资源...");
resource = new ComplexResource();
}
}
public static class ComplexResource {
private String name;
ComplexResource() {
name = "复杂资源-" + System.currentTimeMillis();
}
public void process() {
System.out.println("处理资源: " + name);
}
}
public ComplexResource getResource() {
return ResourceHolder.INSTANCE.resource;
}
}
完整的应用示例
public class CompleteExample {
// 配置管理单例
public enum ConfigManager {
INSTANCE;
private Properties properties = new Properties();
ConfigManager() {
loadDefaultConfig();
}
private void loadDefaultConfig() {
properties.setProperty("app.name", "我的应用");
properties.setProperty("app.version", "1.0.0");
properties.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
properties.setProperty("database.user", "root");
}
public String getProperty(String key) {
return properties.getProperty(key);
}
public void setProperty(String key, String value) {
properties.setProperty(key, value);
}
public void displayConfig() {
System.out.println("=== 应用配置 ===");
properties.forEach((k, v) ->
System.out.println(k + " = " + v));
}
}
public static void main(String[] args) {
// 使用配置管理单例
System.out.println("应用名: " + ConfigManager.INSTANCE.getProperty("app.name"));
System.out.println("数据库URL: " + ConfigManager.INSTANCE.getProperty("database.url"));
// 修改配置
ConfigManager.INSTANCE.setProperty("app.version", "2.0.0");
System.out.println("更新后版本: " + ConfigManager.INSTANCE.getProperty("app.version"));
// 显示所有配置
ConfigManager.INSTANCE.displayConfig();
}
}
防止反射破坏的完整示例
import java.lang.reflect.Constructor;
public enum SafeSingleton implements Cloneable {
INSTANCE;
private String name;
// 防止克隆
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("单例不能被克隆");
}
// 测试反射攻击
public static void testReflection() {
try {
Constructor<SafeSingleton> constructor =
SafeSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
SafeSingleton anotherInstance = constructor.newInstance();
System.out.println("反射创建的实例: " + anotherInstance);
} catch (Exception e) {
System.out.println("反射攻击失败: " + e.getMessage());
}
}
public static void main(String[] args) {
SafeSingleton instance1 = SafeSingleton.INSTANCE;
SafeSingleton instance2 = SafeSingleton.INSTANCE;
System.out.println("两个实例是否相同: " + (instance1 == instance2));
// 测试反射攻击
testReflection();
// 测试克隆
try {
instance1.clone();
} catch (Exception e) {
System.out.println("克隆失败: " + e.getMessage());
}
}
}
枚举单例的核心优势
- 线程安全:枚举实例的创建由JVM保证,天然线程安全
- 防反射攻击:枚举没有公共构造器,反射无法创建新实例
- 防序列化破坏:枚举反序列化时自动复用现有实例
- 防克隆:枚举不能使用clone()方法创建新实例
- 简洁直观:代码简洁,易于理解和使用
最佳实践建议
// 推荐的枚举单例模式
public enum RecommendedSingleton {
INSTANCE;
// 私有字段
private DatabaseConnector db;
private CacheManager cache;
// 构造函数中初始化所有资源
RecommendedSingleton() {
// 初始化资源
db = new DatabaseConnector();
cache = new CacheManager();
}
// 提供业务方法
public void connectDB() {
db.connect();
}
public Object getFromCache(String key) {
return cache.get(key);
}
}
枚举单例是目前公认的最安全的单例实现方式之一,它很好地解决了传统单例模式中存在的线程安全、反射攻击、序列化破坏等问题。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播