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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. class Demo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Single s1=Single.getInstance();
  6.                 Single s2=Single.getInstance();
  7.         }
  8. }
  9. class Single
  10. {
  11.         private Single(){}
  12.         private static Single s=null;
  13.         public static Single getInstance(){
  14.                 if(s==null)
  15.                                 return new Single();
  16.                 return s;

  17.         }
  18. }
复制代码
大神可不可以从内存的角度给解释一下为什么只有一个对象被创建吗?第一次调用getInstance()后创建了对象,第二次调用getInstance()时为什么就不创建了呢?是static修饰的问题吗?

16 个回复

倒序浏览
在我看来好像跟内存没什么关系,因为单例设计模式就是为了只能存在一个实例而创建的。
回复 使用道具 举报
首先要明确,单例设计模式 保证对象唯一性需要做到什么?
       1.为了避免其他程序或过多建立该对象,先禁止其他程序建立该类对象。
       2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
       3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三部用代码体现:
       1.将构造函数私有化。 private Single(){}
       2.在类中创建一个本类对象。private static Single s = null;
       3.提供一个方法可以获取到该对象。public static Single getInstance(){}
构造函数私有化,又自己建立了本类对象,外界便不能建立或修改本类对象了。
s 被 static 修饰,声明周期随类的加载而存在,外界不能建立对象,所以只有一个对象,因此也只有一个 s 。
通过判断 s ,确定是否已经建立了对象。

需注意,懒汉式存在线程问题,使用时要注意选择。
例如下面这个例子:
  1. class Single
  2.   {
  3.              private static Single s = null;//注意要给s赋值,赋值为null。
  4.              private Single(){}  
  5.              public static Single getInstance()
  6.              {
  7.                         if(s==null)
  8.                         {
  9.                                    //-->B;
  10.                                    synchronized(Single.class)
  11.                                    {
  12.                                               if(s==null)
  13.                                                //-->B;A出去后,B在进来判断一下,C以后的只在外层判断就行。
  14.                                                //-->A;
  15.                                                          s = new Single();
  16.                                    }
  17.                         }
  18.                         return s;
  19.              }
  20.   }
  21. <p> </p>
复制代码

回复 使用道具 举报 1 0
  楼上讲的真详细。
回复 使用道具 举报
构造函数被私有化了
回复 使用道具 举报
s 被 static 修饰,声明周期随类的加载而存在,外界不能建立对象,所以只有一个对象,因此也只有一个 s 。
通过判断 s ,确定是否已经建立了对象。

需注意,懒汉式存在线程问题,使用时要注意选择。-------------------
这就是我想要的!!!!谢谢!!!!
回复 使用道具 举报
郑飞 高级黑马 2014-9-16 04:15:36
7#
if(s==null)
                                return new Single();
                return s;
亲 if判断不是白写的 如果存在对象了返回原来的对象s
回复 使用道具 举报
郑飞 发表于 2014-9-16 04:15
if(s==null)
                                return new Single();
                return s;

我的意思是说,被static修饰的Single s刚开始的时候是null,后来第一次运行Single.getInstance()时,s=new Single()了,第二次是不是就是因为static的缘故,s的值固定就是原来new的Single对象了。。。。
都说static修饰的是随着类的加载而加载,怎么个随着类的加载而加载呢,,是不是就是赋值后就不能再变了???????????
回复 使用道具 举报
第二次调用getInstance()时,s!=null,所以不新建对象,返回的还是原来的对象s
回复 使用道具 举报
sean 中级黑马 2014-9-18 23:57:11
10#
设计模式到现在还没怎么理解!哎
回复 使用道具 举报
shuimu_88 发表于 2014-9-18 23:52
第二次调用getInstance()时,s!=null,所以不新建对象,返回的还是原来的对象s ...

我的意思就是说为什么第二次调用getInstance()时,s为什么就不是空了呢???
回复 使用道具 举报
刚开始不存在 s
第一次调用getInstance()当类加载器加载了Single类的同时 静态代码块中 s被初始化为null 然后进入方法判断s 因为s是null 所以就去new Single() 并赋值给s 返回s;
第二次调用getInstance() 因为不存在第二次加载 所以直接进入方法判断s 因为s非空 所以不再new Single() 直接调用当前s 作为返回值;

因为类只会被加载一次 所以static修饰的只会被调用一次 仅此而已 在其他地方照样可以操作s 没影响
回复 使用道具 举报
苏乞儿 发表于 2014-9-19 00:07
我的意思就是说为什么第二次调用getInstance()时,s为什么就不是空了呢??? ...

静态变量随着类的加载而加载,第二次调用getInstance()时,静态变量s不会再加载,因为类已经加载了,不可能重复加载,所以它的值被所有对象共享
回复 使用道具 举报
shuimu_88 发表于 2014-9-19 00:20
静态变量随着类的加载而加载,第二次调用getInstance()时,静态变量s不会再加载,因为类已经加载了,不 ...

嗯,谢谢来。懂了。!:)
回复 使用道具 举报
郑飞 发表于 2014-9-19 00:08
刚开始不存在 s
第一次调用getInstance()当类加载器加载了Single类的同时 静态代码块中 s被初始化为null  ...

“不存在第二次加载”,懂了,谢谢~!
回复 使用道具 举报
单例模式的目的就是只创建一个对象,
私有化构造函数,自己创建一个对象,这样外界就不能创建了。
回复 使用道具 举报
这里的对象是在类进加载的时候建立的,调用getInstance()方法只是令s1或者s2变量指向了该对象,并没有新建立对象。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马