求教 单列模式中延迟初始化和急切初始化的区别

fishmen26 2013-01-10 11:09:41
为什么急切初始化会比延迟初始化更早被初始化?如下代码:

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()调用时, 请问与前一种方式相比有什么好处呢?为什么这种方式就能达到延迟初始化的效果呢?
...全文
502 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
brave_panda 2014-08-13
  • 打赏
  • 举报
回复
引用 2 楼 raistlic 的回复:
(楼上又回来了?) Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInstance 也会被建立。 而 Singleton.SingletonHolder 则不同,SingletonHolder 是 private 的内部类,提到它的唯一的地方在 getInstance() 方法内,所以只有第一次运行 Singleton.getInstance() 方法的时候它才会被加载,而作为它静态成员的 holder 才会被建立。 其实多数情况下一个被设计成单例的类,你第一次提到它的类名一般就是要调用 getInstance() 方法,一般单例的类也只有这一个静态方法,所以第一种就行了。
但是,final static这样的常量,在编译阶段就已经存入class文件的常量池中,那是不是说,再编译阶段就已经初始化完成了? 还是说,分配实例对象的步骤要到调用getlnstance(),编译阶段只是定义其应用类型?
hover00401 2014-06-18
  • 打赏
  • 举报
回复
貌似Singletion.class这个是类字面常量,根本就不会引起类加载,请回家好好看看《Tinking in Java》,然后再打开IDE调试一下再来发表言论,发现论坛里面都是转来转去,又有几个人自己调试过呢
raistlic 2013-01-11
  • 打赏
  • 举报
回复
引用 8 楼 fishmen26 的回复:
引用 7 楼 raistlic 的回复:引用 6 楼 fishmen26 的回复:我感觉你和二楼说的完全不一样呢?你的说法也是书本上的说法,能具体说明为什么吗? 二楼只是做了更多解释 哪里不一样了? bao110908 说: 前者在 Singleton 类初始化后 sInstance 对象就创建了,也就是说在调用 getInstance 之前。 你……
这是你的理解,我可没这么说 我说的是 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInstance 也会被建立。
  • 打赏
  • 举报
回复
这个单例对象产生的时机不一样。 前者在 Singleton 类初始化后 sInstance 对象就创建了,也就是说在调用 getInstance 之前。 后者在调用 getInstance 时,SingletonHolder.holder 对象尚未创建,因为 SingletonHolder 类还没有初始化,当执行到 SingletonHolder. 加载 SingletonHolder 类后 holder 对象开始初始化工作
fishmen26 2013-01-11
  • 打赏
  • 举报
回复
引用 7 楼 raistlic 的回复:
引用 6 楼 fishmen26 的回复:我感觉你和二楼说的完全不一样呢?你的说法也是书本上的说法,能具体说明为什么吗? 二楼只是做了更多解释 哪里不一样了?
bao110908 说: 前者在 Singleton 类初始化后 sInstance 对象就创建了,也就是说在调用 getInstance 之前。 你的解释和我的理解都认为 前者也是在调用getInstance 时才进行初始化。 不是这样吗?
raistlic 2013-01-11
  • 打赏
  • 举报
回复
引用 6 楼 fishmen26 的回复:
我感觉你和二楼说的完全不一样呢?你的说法也是书本上的说法,能具体说明为什么吗?
二楼只是做了更多解释 哪里不一样了?
fishmen26 2013-01-11
  • 打赏
  • 举报
回复
引用 1 楼 bao110908 的回复:
这个单例对象产生的时机不一样。 前者在 Singleton 类初始化后 sInstance 对象就创建了,也就是说在调用 getInstance 之前。 后者在调用 getInstance 时,SingletonHolder.holder 对象尚未创建,因为 SingletonHolder 类还没有初始化,当执行到 SingletonHolder. 加载 Si……
我感觉你和二楼说的完全不一样呢?你的说法也是书本上的说法,能具体说明为什么吗?
fishmen26 2013-01-11
  • 打赏
  • 举报
回复
引用 2 楼 raistlic 的回复:
(楼上又回来了?) Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInsta……
请问只有在 Class<?> singletonType = Singleton.class; 即反射的时候才会有区别吗? 这两种形式还有其他区别吗? 谢谢
笑莫问 2013-01-11
  • 打赏
  • 举报
回复
引用 1 楼 bao110908 的回复:
这个单例对象产生的时机不一样。 前者在 Singleton 类初始化后 sInstance 对象就创建了,也就是说在调用 getInstance 之前。 后者在调用 getInstance 时,SingletonHolder.holder 对象尚未创建,因为 SingletonHolder 类还没有初始化,当执行到 SingletonHolder. 加载 SingletonHolder……
+1
熊猫大虾 2013-01-11
  • 打赏
  • 举报
回复
引用 2 楼 raistlic 的回复:
(楼上又回来了?) Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInsta……
这个一般用于什么情况下呢?
raistlic 2013-01-11
  • 打赏
  • 举报
回复
(楼上又回来了?) Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInstance 也会被建立。 而 Singleton.SingletonHolder 则不同,SingletonHolder 是 private 的内部类,提到它的唯一的地方在 getInstance() 方法内,所以只有第一次运行 Singleton.getInstance() 方法的时候它才会被加载,而作为它静态成员的 holder 才会被建立。 其实多数情况下一个被设计成单例的类,你第一次提到它的类名一般就是要调用 getInstance() 方法,一般单例的类也只有这一个静态方法,所以第一种就行了。
浠月 2013-01-11
  • 打赏
  • 举报
回复
引用 2 楼 raistlic 的回复:
(楼上又回来了?) Java 中类的加载本身是“延迟”的,当你第一次在代码中提到 Singleton 这个类的时候,它才被加载,内部类也是一样的。 换句话说,对于第一种,假如你不调用 Singleton.getInstance(); 而是写: Class<?> singletonType = Singleton.class; 那 sInsta……
+1
raistlic 2013-01-11
  • 打赏
  • 举报
回复
引用 10 楼 fishmen26 的回复:
I am totally confused. 这样理解对吗? 假设 Singleton.getInstance() 是代码中第一句提到Singleton class的地方。那么这两种初始化类的方式没有区别。 谢谢。
没错。
brightyq 2013-01-11
  • 打赏
  • 举报
回复
单例的是否懒加载,也就是单例对象的创建时机的问题. 懒加载, 也就是在不调用getlnstance()方法的时候,Singleton 对象是不创建的. 非懒加载,就是只要主动使用了Singleton ,对象就会被创建. 你的第一个例子,sInstance变量被定义为static类型的,所以第一次主动使用Singleton类的时候,sInstance就会被初始化,也就是单例对建被创建了出来.也即非懒加载. 所以区别就在于对象是什么时候被创建的.至于各自的好处,楼主可以自己理解啊,什么时候要懒加载,它是根据你的需要而定的.如果创建对象不是消耗很大的话,区别并不明显。
fishmen26 2013-01-11
  • 打赏
  • 举报
回复
I am totally confused. 这样理解对吗? 假设 Singleton.getInstance() 是代码中第一句提到Singleton class的地方。那么这两种初始化类的方式没有区别。 谢谢。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧