8.Java设计模式-创建型模式-单例模式-反射对单例的破坏

创建型设计模式——单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。单例模式也比较好理解,比如一个人一生当中只能有一个真实的身份证号,一个国家只有一个政府,类似的场景都是属于单例模式。单例设计模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。 阅读详情


1.反射

反射:在程序运行期间,可以通过反射动态的访问Java对象的属性、方法、构造方法等

下面我将以单例模式-静态内部类的方式来演示反射对单例的破坏


2.实现代码

public class Singleton {
    private Singleton() {
    }

    private static class SingletonHandler {
        private static Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHandler.INSTANCE;
    }
}

上面是单例模式-静态内部类的实现代码,没有学过单例模式-静态内部类的朋友,建议先看完6.Java设计模式-创建型模式-单例模式-静态内部类,这样更利于大家对下面讲解的理解。

public class TestDemo {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println("s1 == s2: " + (s1 == s2)); // s1 == s2: true
    }
}

上面是我们测试的代码,通过Singleton.getInstance获取到的是同一个对象,没有问题,符合单例的特性。
下面我们要开始搞破坏了呦~

import java.lang.reflect.Constructor;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        Class<Singleton> clazz = Singleton.class; // 获取到Singleton的class对象
        Constructor<Singleton> constructor = clazz.getDeclaredConstructor(); // 根据class对象获取到无参构造方法
        constructor.setAccessible(true); // 由于无参构造方法是private的,所以要设置为可访问
        Singleton instance1 = constructor.newInstance(); // 通过反射创建对象
        Singleton instance2 = constructor.newInstance(); // 通过反射创建对象
        System.out.println(instance1 == instance2); // false
    }
}

上面是破坏单例的实现代码,建议大家先把注释的内容看完,再来看下面的讲解。
根据打印结果为false,我们发现,instance1和instance2不是同一个对象,即单例遭到了破坏,即Singleton的实例不是全局唯一的。
发现问题后,该怎么避免呢?
大家想想,在反射的时候,我们调用的是什么方法创建的对象?答案:我们调用的是Singleton的构造方法来创建的对象。
既然反射能随心所欲的操作构造方法,那我们只能在构造方法内部做些文章了。

在这里插入图片描述
在原先代码的基础上,我只加了上图框起来的代码。

如果有人通过反射来调用构造方法,走到if条件语句的时候,会有两种情况

  1. 静态成员变量INSTANCE还没有被创建,那么就会触发静态内部类SingletonHandler的加载,这样子JVM就会帮我们完成INSTANCE的创建,完成创建后,SingletonHandler.INSTANCE就不为null了,即就会抛上图所示的异常
  2. 静态成员变量INSTANCE已经被创建,由于SingletonHandler.INSTANCE不为null,所以就会抛上图所示的异常

大家发现没有,无论INSTANCE有没有被创建,都会抛异常,并且如果INSTANCE没有被创建,还会帮我们完成创建,这样子,不就避免了反射对单例的破坏了么。


3.总结

大家可以就单例模式-饿汉式、单例模式-懒汉式-“synchronized加锁“实现、单例模式-懒汉式-“双重检查锁+volatile“实现,自己来实现一下如何避免反射对单例的破坏,方法和我上面讲的类似,只是实现细节上有些许不同。
由于java底层源码不允许通过反射来创建枚举对象,所以就不存在反射对枚举单例的影响了,那大家可能就有疑问了,java底层源码是怎么不允许的呢?
大家在idea里面全局搜Enum这个类,会发现它是一个抽象类,它只有一个构造方法,且是两个参数的构造方法,第一个参数是String类型的name,第二个参数是int类型的ordinal,所以我用下图所示的代码来测一下反射,看看会发生什么。
测试代码
运行结果
源码
大家会发现运行时抛了Cannot reflectively create enum objects的异常,源码如上图,相信很好理解。


下一篇:9.Java设计模式-创建型模式-单例模式-反序列化对单例的破坏

哇喔!20种单例模式的实现与变异总结 这些变种和扩展可以用来应对不同的使用场景,从安全性到性能需求再到资源管理需求。根据特定需求,可以选择或定制合适的单例实现方式。关注威哥爱编程,编程乐无边。 阅读详情

相关推荐

【Java硬核知识:设计模式落地误区】单例模式的七种写法:从DCL到枚举的终极进化

摘要:单例模式作为 Java 设计模式中最为基础且常用的模式之一,其实现方式多样。本文深入探讨了单例模式的七种常见写法,从双检锁(DCL)到枚举单例的演变过程。着重分析了双检锁中 volatile 的必要性、静态内部类实现延迟加载的原理以及枚举单例防反射攻击的原理。通过详细的实操流程和完整代码示例,帮助开发者正确理解和运用单例模式,避免在实际开发中陷入设计模式落地的误区。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1412

【设计模式精讲】创建型模式之单例模式(饿汉式、懒汉式、双重校验、静态内部类、枚举)

1 ) 定义单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。单例模式也比较好理解,比如一个人一生当中只能有一个真实的身份证号,一个国家只有一个政府,类似的场景都是属于单例模式。2 ) 使用单例模式要做的两件事保证一个类只有一个实例为该实例提供一个全局访问节点3 ) 单例模式结构1 ) 单例的定义单例设计模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

保姆级教程:用海思PQTool搞定ISP图像调试,从参数读取到固件烧录全流程

本文提供海思PQTool的ISP图像调试全流程指南,从参数读取、实时调试到固件烧录,涵盖环境配置、核心功能解析、参数固化及生产部署。通过实战案例和避坑指南,帮助开发者高效提升图像质量,适用于海思开发板的ISP调试与优化。

weixin_30872337的博客 281

【设计模式系列6】单例模式的8种写法及如何防止单例被破坏

单例模式的写法懒汉模式恶汉模式 懒汉模式 恶汉模式

zwx900102的博客 2590

最全中文停用词表(可直接复制)

最全的停用此表整理 词表名 词表文件 中文停用词表 cn_stopwords.txt 哈工大停用词表 hit_stopwords.txt 百度停用词表 baidu_stopwords.txt 机器智能实验室停用词库 scu_stopwords.txt 以上停用词表链接:https://github.com/goto456/stopwords 以下是我常用的1893个停用词,可直接复制 ! " # $ % & ' ( ) * + , - -- . .. ... ....

dilifish的博客 12万+

详解卷积神经网络(CNN)

卷积神经网络(Convolutional Neural Network, CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。

qq_25762497的博客 25万+

JAVA设计模式——创建型模式

JAVA设计模式——创建型模式

这里有一只小马吖 1691

SCI、中科院1区算法应用:(BWO-CNN-BiGRU-Attention)白鲸优化深度学习-融合注意力机制预测程序代码!包含特征可视化,数据Excel导入,直接运行!

BWO 白鲸优化算法,于2022年发表在SCI、中科院1区期刊《Knowledge-Based Systems》上。我们利用该高创新算法对我们的CNN-BiGRU-Attention时序和空间特征结合-融合注意力机制的回归预测程序代码中的超参数进行优化。

weixin_48747334的博客 3264

Java设计模式 —— 【创建型模式】单例模式(八种创建方法)详解

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

知唔猪的博客 1738

MCU 微控制器,在实际项目中如何选型(以 STM32为例)

1.MCU 选型需要考虑的一些因素 2.案例:传感器设备的 MCU 选型

创享 AIOT 的专栏 1万+

uniapp [安卓苹果App端] - 详细实现下载文件保存到用户手机本地,指定文件存储位置路径及文件夹名称下载并保存,Uniapp app端将文件下载保存并储存到指定目录(手机系统存储空间权限检测)

uni-app,安卓Android,苹果ios,安卓app端,苹果App端,uniapp苹果安卓app,app端下载文件,移动端文件下载,并保存到手机本地存储空间,uniapp下载文件保存到手机本地,iOS下载文件怎么保存,系统读写存储空间权限,下载文件到本地详细流程及源代码,保存自定义目录,uniapp,实现下载文件并保存到本地,文件后缀,如何指定手机的存放目录路径url,点击下载文档到手机中并提示存储位置,如何在uniapp中实现文件下载功能,uniApp文件下载,怎么指定文件保存目录,下载报错,没反应

🏆 前端领域优质创作者 1万+

java中如何创建一个不会被反射破坏的单例

前言 单例相信各位都不陌生,从学习java开始就会经常接触到这个概念,首先先来回忆一下什么是单例: 单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去...

ForteScarlet's Blog 1168

Qt C++ 电子海图与作战叠加(Overlay)系统

lab_pos->setText(QString("坐标: X%1 Y%2").arg(p.x(),0,'f',0).arg(p.y(),0,'f',0));lab_distance->setText(QString("距离: %1 海里").arg(dist,0,'f',1));lab_bearing->setText(QString("方位: %1°").arg(bear,0,'f',1));// 绘制S-57海图基底。scene->addText("封锁线").setPos(450,180);

寒寒豆豆软件公司的博客 496

80. Java 枚举类 - 使用枚举实现单例模式

在 Java 中,使用枚举实现单例模式是最简单且安全的方式。相比于传统的单例模式,枚举单例具有防止反射攻击、防止反序列化破坏、天然线程安全以及代码简洁等优势。通过 INSTANCE 枚举常量,可以轻松实现单例模式,并且可以添加成员变量和方法。枚举单例的构造方法是私有的,反射无法创建新实例,反序列化也不会破坏单例的唯一性。虽然枚举单例不支持懒加载和继承其他类,但在大多数场景下,它是最优的选择,尤其是需要全局唯一对象且防止反射和反序列化破坏时。因此,推荐使用枚举单例,除非需要懒加载或继承其他类。

yaoxin521123的博客 1814

openclaw中文版安装教程和常用命令

OpenClaw 中文版的和,涵盖本地一键部署、Docker 隔离部署、阿里云极速部署三种方式,以及六大类高频命令,方便你快速上手和日常运维。

suny8的专栏 3000

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

手把手教你学会单例模式(2)

什么是单例模式 单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,线程中的单例模式常用来做数据源的动态切换)。 本章节主要是讲,线程单例模式、枚举单例模式、容器单例模式以及序列化和反射破坏单例模式的处理。

程冯冯的博客 2万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

单例模式

单例是23中设计模式之一,保证一个类只有一个实例,并且对外提供统一的访问入口。是创建型模式。

MichaelZ的博客 783

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

单例模式大全,反射拆解!你面试要的8种单例都在这!

单例模式几乎是面试中必考的设计模式。单例到底有几种写法呢?每种写法有什么不同,怎么来保证线程安全?反射怎么获取单例模式?被获取后又该怎么更改?本文用奇淫技巧的方式,带你玩转单例模式。单例模式大全,反射拆解!你面试要的8种单例都在这!

iqqcode 784

设计模式之单例模式(通俗易懂--代码辅助理解【Java版】)

创建型模式:工厂方法、抽象方法、建造者、原型、单例。结构型模式有:适配器、桥接、组合、装饰器、外观、享元、代理。行为型模式有:责任链、命令、解释器、迭代器、中介、备忘录、观察者、状态、策略、模板方法、访问者。常用设计模式:单例模式、工厂模式、代理模式、策略模式&模板模式、门面模式、责任链模式、装饰器模式、组合模式、builder模式。单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

qq_45929019的博客 1609

【设计模式】-单例设计模式(创建者模式)

创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为:单例模式工厂方法模式抽象工程模式原型模式建造者模式1.1 单例设计模式单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的...

cnzzs的博客 1096

设计模式之单例模式详解和应用

目录 1 单例模式的应用场景介绍 2 饿汉式单例模式 2.1 静态方法获得私有成员对象 2.2 利用静态代码块与类同时加载的特性生成单例对象 2.3 优缺点 3 懒汉式单例模式 2.1 加锁 2.2 双重检查锁 2.3 静态内部类 4 反射破坏单例 5 序列化破坏单例(扩展知识) 6 注册式单例模式 6.1 枚举式单例模式 6.2 容器式单例 7 线程单例实现ThreadLocal 8 AbstractFactoryBean源码 9 单例模式小结

赵广陆 2359

7.Java设计模式-创建型模式-单例模式-枚举

枚举:用于存放常量 用枚举实现单例很简单,推荐

Runnin_Athena的博客 724

【Java设计模式】二、单例模式

没有重写readResolve方法时,会通过反射创建一个新的对象,从而破坏了单例模式。IF 这一行,被挂起,再被唤醒时继续往下执行,就会创建出两个不同的实例对象。通过流将单例对象,序列化到文件中,然后再反序列化读取出来。发现通过反序列化方式创建出来的对象内存地址,和原对象不一样,单例模式被破坏。如此,再有A、B两个线程同时执行到第一个IF,只能有一个成功创建对象,另一个获取到锁后,第二重判断会告诉它已经有对象实例了。静态内部类在被加载时,不会立即实例化,而是在第一次使用时才会被加载并初始化。

llg___的博客 1367

Java单例模式8种方式 详解

Singleton 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该由人来控制,而应该由代码来限制,强制单例。 运用场景很多,例如网站的在线人数,window系统的任务管理器,网站计数器等等,这些都是单例模式的运用。单例模式有常见的8种形式,如下: 1.Lazy1【不可用】 懒汉式1: 线程不稳定 延迟初始化 多线程不安全 是最基本的实现方式,不支持多线程,因为没有synchronized加锁,多线程不能工作。 实现图 多线程则会出现,当Singleton_La

ONLY1024的博客 4213

Java设计模式之单例模式

文章目录简介实现总结 简介 实现 总结

qq_18581221的博客 6798

Java设计模式之单例模式最佳实践

Java设计模式之单例模式最佳实践 //新建枚举类 public enum EnumInstance { INSTANCE; private Object data; public Object getData() { return data; } public void setData(Object data) { ...

Crook的专栏 381
上一篇: 7.Java设计模式-创建型模式-单例模式-枚举
下一篇: 9.Java设计模式-创建型模式-单例模式-反序列化对单例的破坏
Bigger K
博客等级 码龄7年 172粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值