A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© sunalong 中级黑马   /  2013-7-15 17:36  /  1165 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨兴庭 于 2013-7-16 17:49 编辑

我知道单例的两个创建方式:

  1. //饿汉式
  2. class Single{
  3. private Single(){} //私有化构造函数。
  4. private static Single s = new Single(); //创建私有并静态的本类对象。
  5. public static Single getInstance(){ //定义公有并静态的方法,返回该对象。
  6.   return s;
  7.   }
  8. }
  9. ---------------------------------------------
  10. //懒汉式:延迟加载方式。
  11. class Single2{
  12. private Single2(){}
  13. private static Single2 s = null;
  14. public static Single2 getInstance(){
  15.   if(s==null)
  16.    s = new Single2();
  17.   return s;
  18.   }
  19. }
复制代码
但在程序内部是怎么被调用的?
今天吃饭时问同学一个问题是关于反射的,他当时就说单例什么的内部是用反射调用的,我当时喝的头都大了,
没仔细问,所以现在问一下、、

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

5 个回复

倒序浏览
单例不需要用到反射吧,单例只是对构造函数进行私有化,然后再建个静态方法返回该对象的就行啦,根本不需要用到反射呀
回复 使用道具 举报
我说一下我的理解,有可能片面,但确实可以实现:

单例设计模式,最核心的思想就是不能创建对象,所有的内容都是通过类名调用,保证其唯一性。

但是,如果用到反射技术,单例的这种不能创建对象唯一性的特性,将会被打破。

例如:利用反射,获取单例设计模式的私有化构造函数,然后创建新的对象,完全可以实现。

因此,单例设计模式(如:楼主所列出的饿汉式,懒汉式)只是一个最基本的雏形,若要保证其唯一性,在实用过程中,需要加入诸多判断,来保证其唯一性。方式有好多种,至于如何实现,就自己找找吧。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
饿汉式(先初始化对象,Single类一进内存就创建好了对象)
懒汉式(延时加载  Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象)
具体过程包括:
<1> 将构造函数私有化  
<2> 在类中创建一个本类对象      
<3> 提供一个方法可以获取到该对象     
懒汉模式主要作用是保证在Java应用程序中,一个类Class只有一个实例在。
使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回(garbage collection)。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
用反射打破单例只能用暴力反射(普通反射是不能打破私有,只能用暴力)
但是你用到暴力反射的话,无论你怎么封装都没用,除了自定义类加载器加密类以外
如果用自定义类加载器加密加载类,你的类要给别人用,对应的类加载器还是也要给别人用
别人还是可以暴你的类加载器,继而暴你的封装类.

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
单例模式其实用反射可以打破的,也就是单例模式的安全性也没有用,因为反射可以直接打破。下面给楼主看下反射式如何打破单例的
  1. package cn.itcast.reflect1;

  2. import java.lang.reflect.Constructor;

  3. public class Test {

  4.         /**
  5.          * @param args
  6.          * @throws Exception
  7.          */
  8.         public static void main(String[] args) throws Exception {
  9.                 Class cls = Class.forName("cn.itcast.reflect1.Single");//获取单例的字节码文件
  10.                 Constructor con = cls.getDeclaredConstructor();//返回构造函数因为单例是私有的构造函数,所以需要强行获取
  11.                 con.setAccessible(true);//强行获取
  12.                 Object obj = con.newInstance();//利用构造函数创建对象
  13.                 System.out.println(obj);//输出对象的哈希值
  14.                 Object obj2 = con.newInstance();//在获取一个对象
  15.                 System.out.println(obj2);//输出对象哈希值
  16.                 /*
  17.                  * 两个哈希值是不相等的,所以单例也可以打破的,用反射
  18.                  */
  19.                
  20.         }

  21. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马