有如下单例模式设计代码:

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破坏单例设计模式的更多相关文章

  1. JAVA之旅(六)——单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖

    JAVA之旅(六)--单例设计模式,继承extends,聚集关系,子父类变量关系,super,覆盖 java也越来越深入了,大家加油吧!咱们一步步来 一.单例设计模式 什么是设计模式? JAVA当中有 ...

  2. java笔记之静态修饰附和单例设计模式

     第六天笔记 静态修饰符static: 一.static修饰成员变量: static用来修饰成员变量叫静态成员变量,没有static修饰的成员变量叫非静态成员变量 静态成员的访问方式: (1)   用 ...

  3. java中你确定用对单例了吗?

    作为程序员这样的特殊物种来说,都掌握了一种特殊能力就是编程思想,逻辑比較慎重,可是有时候总会忽略到一些细节,比方我,一直以来总认为Singleton是设计模式里最简单的,不用太在意,然而就是由于这样的 ...

  4. 如何使用双重检查锁定在 Java 中创建线程安全的单例?

    这个 Java 问题也常被问: 什么是线程安全的单例,你怎么创建它.好吧,在Java 5之前的版本, 使用双重检查锁定创建单例 Singleton 时,如果多个线程试图同时创建 Singleton 实 ...

  5. 单例设计模式(Singleton)

    一.单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法) 例如:Hibernate的Se ...

  6. JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

    JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...

  7. Java中如果把构造方法也私有化,如何创建对象?Java的单例设计模式——饿汉式和懒汉式区别

    Java的单例模式——饿汉式 package com.swift; //Java单例设计模式——恶汉式 public class SinglePerson { private String name= ...

  8. Java中常用来处理时间的三个类:Date、Calendar、SimpleDateFormate,以及Java中的单例设计模式:懒汉式、饿汉式以及静态内部类式

    (一)java.util.Date类 1.该类有一个long类型的属性:用来存放时间,是用毫秒数的形式表示,开始的日期是从1970年1月1号 00:00:00.    2.该类的很多方法都已经过时,不 ...

  9. 对Java单例设计模式中懒汉式类定义的讨论

    全世界人民都知道单例设计模式中类的定义分为懒汉式和饿汉式两种,然而今天并不是要把它们做横向比较.实际上,不论饿汉式类的代码看起来有多么美轮美奂,在实际开发中它的效率总是不如懒汉式的.然而在笔试和面试中 ...

随机推荐

  1. [.net]数组

    在C语言中,数组是比较简单,也使用比较多的一种基础的数据结构.常用的有一维数组,二维数组等.但是在C#中,使用最多的是List,Dictionary等一些集合类,因为用他们来操作同类型的数据,比数组更 ...

  2. day 77 基于form组件的注册功能

    Form 表单 py文件 from django import forms #定义一个form类注册用 class RegForm (forms.Form): username =forms.Char ...

  3. Stack栈类与、Queue队列与线性表的区别和联系

    栈和队列都属于特殊的线性表   一.定义   1.线性表(linear list): 是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列.数据元素是一个抽象的符号,其具体含义在不同的情 ...

  4. mysql 数据备份 crontab

    每天凌晨 2 点备份数据 crontab -e 0 2 * * * mysqldump ${mysqldir}/bin/mysqldump  -h$host -P$port -uadmin -p&qu ...

  5. maven添加仓库没有的jar包

    mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.2.0.4.0 -Dpackaging= ...

  6. 记一次使用SecureCRT连接局域网巨慢的问题

    环境:Win7 32bit + SecureCRT 6.5 中文 使用工作机上的SecureCRT登录公司内网的跳板机,发现很慢,每次都得等待好几分钟才弹出输出私匙密码的框.咨询了一下其他同事,发现他 ...

  7. 读/写锁的实现和应用(高并发状态下的map实现)

    程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源.但是如果有一个线程想去写这些共享资 ...

  8. J05-Java IO流总结五 《 BufferedInputStream和BufferedOutputStream 》

    1. 概念简介 BufferedInputStream和BufferedOutputStream是带缓冲区的字节输入输出处理流.它们本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流 ...

  9. Linux下面安装swoole

    需要安装php7 新建一个文件夹,作为存储swoole的文件夹 然后执行下面相对应的命令,这里是我执行的命令 新建文件夹 mkdir swoole 切入到文件夹中,进行下载安装包 wget http: ...

  10. 使用openssh-clients的scp命令来传输文件

    了解openssh-client是请参阅:https://blog.csdn.net/u010215256/article/details/53239905 了解scp命令来传输文件请参阅:https ...