设计模式之单例模式(Java)

单例模式实现方式:懒汉式、饿汉式、双重检查、枚举、静态内部类;

懒汉式:

/*** 懒汉式单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public class LazySingleton implements Serializable {private static LazySingleton lazySingleton=null;private LazySingleton(){}//特点:第一次调用才初始化,避免内存浪费。public synchronized static LazySingleton getInstance(){if(lazySingleton==null){lazySingleton=new LazySingleton();}return lazySingleton;}
}

饿汉式:

/**饿汉式单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public class HungrySingleton {static final HungrySingleton hungrySingleton=new HungrySingleton();private HungrySingleton(){}//特点:类加载时就初始化,线程安全public static HungrySingleton getInstance(){return hungrySingleton;}
}

双重检查:

和懒汉式的区别就是,锁的范围减小了,防止多线程场景下创建多个实例,所以又加了一层判断。

/**双重检查单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public class DoubleCheckSingletion {private static DoubleCheckSingletion doubleCheckSingletion=null;private DoubleCheckSingletion(){}//特点:安全且在多线程情况下能保持高性能public static DoubleCheckSingletion getInstance(){if(doubleCheckSingletion==null){synchronized (DoubleCheckSingletion.class){if(doubleCheckSingletion==null){doubleCheckSingletion=new DoubleCheckSingletion();}}}return doubleCheckSingletion;}
}

枚举:

/**枚举形单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public enum EnumSingleton {INSTANCE;//特点:自动支持序列化机制,绝对防止多次实例化public static EnumSingleton getInstance(){return INSTANCE;}
}

静态内部类:

/**静态内部类单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public class StaticInnerClassSingleton {private static class InnerClass{private static StaticInnerClassSingleton staticInnerClassSingleton=new StaticInnerClassSingleton();}private StaticInnerClassSingleton(){}public static StaticInnerClassSingleton getInstance(){return InnerClass.staticInnerClassSingleton;}
}

序列化或反射破坏单列模式:

通过序列化反序列化或反射可以破坏除枚举以外的其它实现方式:

LazySingleton instance = LazySingleton.getInstance();//序列化破坏单例模式ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singletion"));oos.writeObject(instance);ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singletion"));LazySingleton instance2 = (LazySingleton) ois.readObject();System.out.println(instance);System.out.println(instance2);System.out.println(instance2==instance);

运行:

解决反序列化破坏单列模式

解决方法只需要在单例类里加上一个readResolve()方法即可,原因就是在反序列化的过程中,会检测readResolve()方法是否存在,如果存在的话就会反射调用readResolve()这个方法。

private Object readResolve(){return lazySingleton;}

使用枚举单例模式天然就可以防止序列化破坏单例模式:

 EnumSingleton instance = EnumSingleton.getInstance();ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singletion"));oos.writeObject(instance);ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singletion"));EnumSingleton instance2 = (EnumSingleton) ois.readObject();System.out.println(instance);System.out.println(instance2);System.out.println(instance==instance2);

运行:

为什么?

  • 枚举类的序列化保证单例: Java枚举类型在序列化和反序列化时会被特殊处理。在序列化的过程中,只是将枚举对象的名字(即枚举常量的名字)写入到序列化文件中;在反序列化的过程中,通过名字来获取枚举对象。这保证了在反序列化过程中无论如何都只会得到枚举中定义的枚举常量,而不会重新创建新的对象。因此,枚举类型的单例模式在反序列化过程中也能保持单例的状态,不会被破坏。

  • 禁止反射创建多个实例: 枚举类型的单例模式天然地禁止了通过反射机制来创建多个实例。枚举类型的构造器是私有的,并且编译器会确保枚举常量只能被实例化一次。如果尝试使用反射来调用枚举类型的私有构造器来创建新的实例,会抛出IllegalArgumentException异常,从而保证了单例的唯一性。

 

反射破坏单例模式:

/**反射破坏单例模式* @author: 小手WA凉* @create: 2024-07-06*/
public class BrokenSingletonTest2 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {LazySingleton instance = LazySingleton.getInstance();Class<LazySingleton> lazySingletonClass = LazySingleton.class;Constructor<LazySingleton> constructor = lazySingletonClass.getDeclaredConstructor();constructor.setAccessible(true);LazySingleton refInstance = constructor.newInstance();System.out.println(instance);System.out.println(refInstance);System.out.println(instance==refInstance);}
}

 运行:

枚举天然也可以防止反射破坏单例模式:

        EnumSingleton instance = EnumSingleton.getInstance();Class<EnumSingleton> singletonClass = EnumSingleton.class;Constructor<EnumSingleton> constructor = singletonClass.getDeclaredConstructor(String.class,int.class);constructor.setAccessible(true);EnumSingleton refInstance = constructor.newInstance();System.out.println(instance);System.out.println(refInstance);System.out.println(instance==refInstance);

运行:

这也是为什么枚举是实现单例模式最好的方式原因之一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/42123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对BSV区块链的曼达拉网络通俗易懂的解释

​​发表时间&#xff1a;2023年6月15日 BSV区块链正在引入“曼达拉”升级&#xff0c;使BSV区块链网络的拓扑结构能够适配Teranode&#xff0c;适配这个可以大幅扩容的节点软件。BSV区块链上曼达拉网络的概念并不会改变整个系统的核心规则&#xff1b;相反&#xff0c;它能够引…

为什么https比http更安全

读完本文&#xff0c;希望你能明白&#xff1a; HTTP通信存在什么问题HTTPS如何改进HTTP存在那些问题HTTPS工作原理是什么 一、什么是HTTPS HTTPS是在HTTP上建立SSL加密层&#xff0c;并对传输数据进行加密&#xff0c;是HTTP协议的安全版。现在它被广泛用于万维网上安全敏感…

【qt】如何获取本机的IP地址?

需要用到这个类QHostInfo和pro里面添加network模块 用这个类的静态函数forName()来获取该主机名的信息 返回的就是这个类 这个QHostInfo类就包括主机的IP地址信息 用静态函数addresses()来获取 返回的是一个QHostAddress的容器 QList<QHostAddress>addrList hostIn…

Laravel队列机制深度解析:异步任务处理的高效之道

Laravel队列机制深度解析&#xff1a;异步任务处理的高效之道 Laravel的队列系统是一个强大的工具&#xff0c;用于执行后台任务和异步处理。它允许开发者将耗时的任务&#xff0c;如发送邮件、处理图片等&#xff0c;放入队列中&#xff0c;然后由后台工作进程异步执行。本文…

Docker 镜像移动或复制到另一台服务器

在实际的开发和部署过程中&#xff0c;我们可能需要将 Docker 镜像从一台服务器移动或复制到另一台服务器。本文将详细介绍如何实现这一操作&#xff0c;帮助你更好地管理和迁移 Docker 镜像。 一、使用 docker save 和 docker load 命令 docker save 和 docker load 是 Dock…

课题申报书中要用的思路图(技术路线图)30张,超高清!

最近在弄课题申报书的时候&#xff0c;需要画“技术路线图”&#xff1b;和小伙伴们探讨才发现很多人居然不会画这种图&#xff0c;还有很多人在Word里面一点一点拼凑…… 我给大家收集了网上非常热门的30张“技术路线图”&#xff0c;但网上流传的都太模糊了&#xff0c;想看…

KBPC3506-ASEMI储能专用整流桥KBPC3506

编辑&#xff1a;ll KBPC3506-ASEMI储能专用整流桥KBPC3506 型号&#xff1a;KBPC3506 品牌&#xff1a;ASEMI 封装&#xff1a;KBPC-4 正向电流&#xff08;Id&#xff09;&#xff1a;35A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;600V 正向浪涌电流&#xf…

基于RK3588的8路摄像头实时全景拼接

基于RK3588的8路摄像头实时全景拼接 输入&#xff1a;2路csi转8路mpi的ahd摄像头&#xff0c;分辨率1920 * 1080 8路拼接结果&#xff1a; 6路拼接结果&#xff1a; UI界面&#xff1a; UI节目设计原理

SpringBoot新手快速入门系列教程一:window上编程环境安装和配置

首先编译器&#xff0c;建议各位不要去尝试AndroidStudio和VisualStudio来做SpringBoot项目。乖乖的直接下载最新版即可 https://www.jetbrains.com.cn/idea/ 当然这是一个收费的IDE&#xff0c;想要便宜可以想办法去某宝买授权&#xff0c;仅供学习参考用&#xff01;赚了钱…

Spring Boot中的多租户架构实现

Spring Boot中的多租户架构实现 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 一、引言 随着云计算和SaaS&#xff08;软件即服务&#xff09;模式的流行&a…

Matlab中collectPlaneWave函数的应用

查看文档如下&#xff1a; 可以看出最多5个参数&#xff0c;分别是阵列对象&#xff0c;信号幅度&#xff0c;入射角度&#xff0c;信号频率&#xff0c;光速。 在下面的代码中&#xff0c;我们先创建一个3阵元的阵列&#xff0c;位置为&#xff1a;&#xff08;-1,0,0&#x…

52-3 权限维持 - IFEO注入(镜像劫持)

IFEO注入(映像劫持)介绍 IFEO(Image File Execution Options)位于Windows注册表中的路径为: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options IFEO最初设计用于为在默认系统环境下可能出现错误的程序提供特殊的调试和执…

MySQL 常见错误及解决方案

1. Too many connections 运行环境&#xff1a;Winows11、Phpstudy V8.1.1.3、MySQL 5.7.26 同一时间 MySQL 的连接数量有限制&#xff0c;当超过上限时将提示下面错误信息&#xff1a; 1040 - Too many connections 查看当前最大连接数 mysql> show variables like %max_…

Android实现获取本机手机号码

和上次获取设备序列号一样&#xff0c;仍然是通过无障碍服务实现&#xff0c;在之前的代码基础上做了更新。代码和demo如下&#xff1a; package com.zwxuf.lib.devicehelper;import android.accessibilityservice.AccessibilityService; import android.app.Activity; import…

css 选择器汇总

目录 所有选择器伪类选择器 所有选择器 选择器用法id选择器#myid类选择器.myclassname标签选择器div,h1,p相邻选择器h1p子选择器ul > li后代选择器li a通配符选择器*属性选择器a[rel“external”]伪类选择器a:hover, li:nth-child 伪类选择器 在CSS3中新增了一个结构伪类选…

Bpuzzle V1.2 支持任意图片!BlueLife Puzzle (bPuzzle) 是一款简单的游戏,通过按正确的顺序滑动拼图块来玩

BlueLife Puzzle (bPuzzle) 是一款简单的游戏&#xff0c;通过按正确的顺序滑动拼图块来玩。将您选择的图像拖放到主窗口或使用文件菜单选择默认图像。如果图片格式是 JPG&#xff0c;大小无关紧要&#xff0c;但如果是 Png&#xff0c;则应为 800600 像素&#xff0c;然后 bPu…

nginx配置尝试

from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import JSONResponse, FileResponse, HTMLResponse import logging import os from datetime import datetime import uvicorn# 初始化日志 logging.basicConfig(filenamefile_server.lo…

详细的讲解一下网络变压器应用POE ,AT BT AF BF的概念,做电路连接指导分析

网络变压器在应用POE&#xff08;Power over Ethernet&#xff09;技术时&#xff0c;承担着重要的角色。它不仅负责数据的传输&#xff0c;同时也为网络设备提供电力。在IEEE 802.3标准中&#xff0c;定义了几个与POE相关的标准&#xff0c;包括802.3af、802.3at、802.3bt等&a…

智慧景区解决方案PPT(89页)

智慧景区解决方案摘要 解决方案概述智慧景区解决方案旨在利用现代信息技术解决景区管理机构面临的保护与发展矛盾&#xff0c;推动服务职能转变&#xff0c;促进旅游产业跨越式发展&#xff0c;实现旅游经营增长和管理成本优化。 宏观政策背景国家旅游局发布的《“十三五”全国…

VideoAgent——使用大规模语言模型作为代理来理解长视频

概述 论文地址&#xff1a;https://arxiv.org/pdf/2403.10517 本研究引入了一个新颖的基于代理的系统&#xff0c;名为 VideoAgent。该系统以大规模语言模型为核心&#xff0c;负责识别关键信息以回答问题和编辑视频。VideoAgent 在具有挑战性的 EgoSchema 和 NExT-QA 基准上进…