Java中反射和Unsafe破坏单例设计模式
有如下单例模式设计代码:
class Singleton
{
private String info = "HELLO SHIT"; private static Singleton instance; private Singleton()
{
System.out.println("******实例化对象******");
} public static Singleton getInstance()
{
synchronized (Singleton.class)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
} public void show()
{
System.out.println("www.google.com");
}
}
按照规则,我们只能获取一个实例化的对象,如下面的代码:
public class Hello
{
public static void main(String[] args) throws Exception
{
Singleton instanceA = Singleton.getInstance();
Singleton instanceB = Singleton.getInstance();
System.out.println(instanceA.hashCode());
System.out.println(instanceB.hashCode());
System.out.println(instanceA == instanceB);
}
}
程序输出:
******实例化对象******
685325104
685325104
true Process finished with exit code 0
可以看到instanceA和instanceB完全相同.
下面演示用反射获取单例的构造函数,并且实例化出多个对象:
public class Hello
{
public static void main(String[] args) throws Exception
{
Constructor c = Singleton.class.getDeclaredConstructor();
c.setAccessible(true); Singleton instanceA = (Singleton)c.newInstance();
Singleton instanceB = (Singleton)c.newInstance();
System.out.println(instanceA.hashCode());
System.out.println(instanceB.hashCode());
System.out.println(instanceA == instanceB);
}
}
程序输出:
******实例化对象******
******实例化对象******
685325104
460141958
false Process finished with exit code 0
可以看到,这里调用了两次构造函数,实例化了两个不同的Singleton对象。
除了用反射,我们还可以用Unsafe类实例化多个单例对象,这种方式和反射的区别在于:Unsafe不需要调用构造函数。因为Unsafe是使用C++进行JVM底层控制。代码如下:
public class Hello
{
public static void main(String[] args) throws Exception
{
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe unsafeInstance = (Unsafe)theUnsafeField.get(null);
Singleton instanceA = (Singleton)unsafeInstance.allocateInstance(Singleton.class);
Singleton instanceB = (Singleton)unsafeInstance.allocateInstance(Singleton.class);
System.out.println(instanceA.hashCode());
System.out.println(instanceB.hashCode());
System.out.println(instanceA == instanceB);
}
}
程序输出:
460141958
1163157884
false Process finished with exit code 0
可以发现上面的代码根本没有调用Singleton的构造函数,而是直接生成了两个实例。
其实上面的代码并没有太大意义,只是作为知识点可以加深对反射和单例的理解和印象。
Java中反射和Unsafe破坏单例设计模式的更多相关文章
- JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖
JAVA之旅(六)--单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖 java也越来越深入了,大家加油吧!咱们一步步来 一.单例设计模式 什么是设计模式? JAVA当中有 ...
- java笔记之静态修饰附和单例设计模式
第六天笔记 静态修饰符static: 一.static修饰成员变量: static用来修饰成员变量叫静态成员变量,没有static修饰的成员变量叫非静态成员变量 静态成员的访问方式: (1) 用 ...
- java中你确定用对单例了吗?
作为程序员这样的特殊物种来说,都掌握了一种特殊能力就是编程思想,逻辑比較慎重,可是有时候总会忽略到一些细节,比方我,一直以来总认为Singleton是设计模式里最简单的,不用太在意,然而就是由于这样的 ...
- 如何使用双重检查锁定在 Java 中创建线程安全的单例?
这个 Java 问题也常被问: 什么是线程安全的单例,你怎么创建它.好吧,在Java 5之前的版本, 使用双重检查锁定创建单例 Singleton 时,如果多个线程试图同时创建 Singleton 实 ...
- 单例设计模式(Singleton)
一.单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法) 例如:Hibernate的Se ...
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制
JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...
- Java中如果把构造方法也私有化,如何创建对象?Java的单例设计模式——饿汉式和懒汉式区别
Java的单例模式——饿汉式 package com.swift; //Java单例设计模式——恶汉式 public class SinglePerson { private String name= ...
- Java中常用来处理时间的三个类:Date、Calendar、SimpleDateFormate,以及Java中的单例设计模式:懒汉式、饿汉式以及静态内部类式
(一)java.util.Date类 1.该类有一个long类型的属性:用来存放时间,是用毫秒数的形式表示,开始的日期是从1970年1月1号 00:00:00. 2.该类的很多方法都已经过时,不 ...
- 对Java单例设计模式中懒汉式类定义的讨论
全世界人民都知道单例设计模式中类的定义分为懒汉式和饿汉式两种,然而今天并不是要把它们做横向比较.实际上,不论饿汉式类的代码看起来有多么美轮美奂,在实际开发中它的效率总是不如懒汉式的.然而在笔试和面试中 ...
随机推荐
- ueditor图片上传插件的使用
在项目里使用到ueditor图片上传插件,以前图片上传都是直接使用js代码直接上传图片,比较麻烦,而且效率也比较低,而ueditor这款插件完美的解决了这个问题,这个是百度开发的一款富文本编辑器,在这 ...
- js中null, undefined 和 typeof
参考自:http://www.cnblogs.com/wicub/p/3442891.html typeof 是运算符,注意不是函数,是运算符,其作用,是考察变量究竟是什么类型.或曰,是变量是否定义或 ...
- InnoDB之锁机制
前两天听了姜老大关于InnoDB中锁的相关培训,刚好也在看这方面的知识,就顺便利用时间把这部分知识做个整理,方便自己理解.主要分为下面几个部分 1. InnoDB同步机制 InnoDB存储引擎有两种同 ...
- 数组序列化serialize
1,数据在网络中是以字符串形式传输,这样如果传输的是数组,首先将数组内容拼接成字符串进行发送,接收方拿到字符串,没法将其还原为数组.因此在网络传输的时候,为了保证数据类型的不丢失,先序列化,再发送. ...
- 我与网站的日常-webshell命令执行
本文比较基础,其中有一个知识点关于php执行系统命令的函数 ,我们用最简单的webshell来说说传值问题的影响, 本文作者: i春秋签约作家——屌丝绅士 0×01前言: 小表弟又来写文章了,这 ...
- [转][SQL]如何实现存储过程中动态加入条件---没想到语句可以这么巧妙
在存储过程过程中,如果要实现Select查询的where子句动态查询,可以用exec ( "select .... where" +@whereStr)这样的方式.但这样的话,感觉 ...
- 将一个List拆分为n份的方法
public static void main(String[] args) { List<Integer> taskList = new ArrayList<>(); for ...
- leetcode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
目录 题目描述: 示例: 解法: 题目描述: 给定一个二叉树,原地将它展开为链表. 示例: 给定二叉树 1 / \ 2 5 / \ \ 3 4 6 将其展开为: 1 \ 2 \ 3 \ 4 \ 5 \ ...
- Java Web入门学习(三)Maven的配置与使用国内仓库
一.Maven下载与配置 下载好的压缩包,压缩到D盘,或者其他盘符. 新建系统环境变量 MAVEN_HOME 值是压缩好的Maven目录. 比如: D:\apache-maven- 在path环境变 ...
- (转)解锁MySQL备份恢复的4种正确姿势
本文根据DBAplus社群第104期线上分享整理而成. 原文:http://dbaplus.cn/news-11-1267-1.html 讲师介绍 冯帅 点融网高级DBA 获有Oracle OCM ...