日期:2014-05-20  浏览次数:20617 次

求教 单列模式中延迟初始化和急切初始化的区别
为什么急切初始化会比延迟初始化更早被初始化?如下代码:

public class Singleton {
         Singleton1(){}
         private final static Singleton sInstance=new Singleton();

         public static Singleton getlnstance(){
            return sInstance;
         }
}

请问sInstance 的初始化发生在什么时候? 我理解它发生在getlnstance()函数被调用时。原因如下:

sInstance 的赋值对象不是一个常量(是一个变量,即Singleton()),所以它应该在自己被调用时才初始化。也就是getlnstance()调用时。

请问我的理解对吗?

在Effective java 中还提到一种延迟初始化的方式

public class Singleton {
         Singleton1(){}
         private static class SingletonHolder {
               final static Singleton holder=new Singleton();

         }
         public static Singleton getlnstance(){
            return SingletonHolder.holder;
         }
}

在这种方式下 Singleton 的初始化时间也是getlnstance()调用时, 请问与前一种方式相比有什么好处呢?为什么这种方式就能达到延迟初始化的效果呢?

------解决方案--------------------
(楼上又回来了?)


Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。

换句话说,对于第一种,假如你不调用  Singleton.getInstance(); 而是写:

Class<?> singletonType = Singleton.class;

那 sInstance 也会被建立。


而 Singleton.SingletonHolder 则不同,SingletonHolder 是 private 的内部类,提到它的唯一的地方在 getInstance() 方法内,所以只有第一次运行 Singleton.getInstance() 方法的时候它才会被加载,而作为它静态成员的 holder 才会被建立。



其实多数情况下一个被设计成单例的类,你第一次提到它的类名一般就是要调用 getInstance() 方法,一般单例的类也只有这一个静态方法,所以第一种就行了。
------解决方案--------------------
单例的是否懒加载,也就是单例对象的创建时机的问题.
懒加载, 也就是在不调用getlnstance()方法的时候,Singleton 对象是不创建的.
非懒加载,就是只要主动使用了Singleton ,对象就会被创建.

你的第一个例子,sInstance变量被定义为static类型的,所以第一次主动使用Singleton类的时候,sInstance就会被初始化,也就是单例对建被创建了出来.也即非懒加载.

所以区别就在于对象是什么时候被创建的.至于各自的好处,楼主可以自己理解啊,什么时候要懒加载,它是根据你的需要而定的.如果创建对象不是消耗很大的话,区别并不明显。