- 浏览: 17491 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
runningship:
我个人表示支持楼主,楼主多多交流啊
论Hibernate,狭隘化了的ORM模型 -
theoffspring:
第一种就行了,比双重锁check要简单。
非线程同步机制下线程安全的单例模式——最优的单例模式 -
david3083:
画蛇添足
非线程同步机制下线程安全的单例模式——最优的单例模式 -
lishaorui:
单例模式,楼主提到的第一种是比较好的。这些内容在研磨设计模式和 ...
非线程同步机制下线程安全的单例模式——最优的单例模式 -
rentianchou:
我现在也有这打算 可是项目忙 么有时间
成功破解Myeclipse9之后,开始转向IntelliJ idea 10
个人认为下面是Java实现的最优的单例模式
这种实现方法采用内部静态类,
只在第一次调用getInstance方法的时候才实例化单例对象
如果不调用,就不会进行单例对象的实例化,
因此,既实现了延迟实例化,又不需要线程同步
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
下面这种就是
还有两种解决方案,不在本帖讨论范围之内
1.采用synchronized的关键字同步getInstance方法
2.采用synchronized的关键字同步代码段,双重是否为空的判断
关于Class.forName对一个类实例化时,static关键字修饰的变量初始化与否与类加载器有关,
默认forName0(className, true, ClassLoader.getCallerClassLoader());
如果为forName0(className, false, ClassLoader.getCallerClassLoader());那么就不会初始化类中的static变量
http://technoboy.iteye.com/blog/1005718
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
“静态代码块执行顺序要晚于静态字段”
这句话不准确。静态代码的初始化顺序取决于 声明的顺序,没有绝对的 静态代码块晚于静态字段。
看下面的代码:
其实,本质上来说:
完全等价于:
它们只是两种不同的书写方法而已。不止静态变量,实例变量也是一样。
实例变量的初始化可以以3种形式定义,但编译器编译的时候,会把各种形式的初始化语句按出现顺序放到构造函数中。
等价于:
嗯,你说的对,以后得多向你学习了~
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
“静态代码块执行顺序要晚于静态字段”
这句话不准确。静态代码的初始化顺序取决于 声明的顺序,没有绝对的 静态代码块晚于静态字段。
看下面的代码:
其实,本质上来说:
完全等价于:
它们只是两种不同的书写方法而已。不止静态变量,实例变量也是一样。
实例变量的初始化可以以3种形式定义,但编译器编译的时候,会把各种形式的初始化语句按出现顺序放到构造函数中。
等价于:
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
说错,确实是达到延迟加载。只不过看出去有点怪。
呵呵,大家都很热衷技术啊,好现象~
我个人认为带懒加载的最优单例模式是楼主说的第二种,不知大家认为如何。
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
说错,确实是达到延迟加载。只不过看出去有点怪。
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
这个受教了,但是这个也只是对Class.forName有用吧,
一旦你调用了该类的其他方法或者引用该类信息的时候就会实例化吧?
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
完全等价于:
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
声明一下,这里讲延迟加载,就是你不显示call 实例的时候,不会实例化,至于你调其他方法什么的,木有关系
何来纠结,只是讨论延迟加载的问题~
这个受教了,但是这个也只是对Class.forName有用吧,
一旦你调用了该类的其他方法或者引用该类信息的时候就会实例化吧?
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
完全等价于:
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
这种方式下的确 是延迟到getInstance()方法被调用的时候才实例化new SingleTon();
这种方式下new SingleTon();是在SingleTon类被加载的时候才初始化的,SingleTon类被加载的时机是
该类第一次被引用的时候。所以,什么时候加载不确定。
但一般引用SingleTon类的代码被执行的时候,也就是需要使用的时候了,所以实质上也有延迟的效果。
比如下面的代码:
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
完全等价于:
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
类加载的时候,对于静态变量与块,从上而下逐个执行。延迟加载是用的时候才实例化。
public static void main(String[] args) {
SingleTon instance = SingleTon .getInstance();// 在这个地方设断点
}
可以通过这个在测试。是否是延迟加载的
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
你敢实际测试一下么?
你不调用,它会实例化?
多的俺不说了,如果你觉得他是延迟加载的,你提供测试方法出来,或者说下静态类、嵌套类中静态实例在类加载的时候是怎么加载的
测试结果出来了,你还有什么话说?
唉,眼高手低的人~~~~~~
这种实现方法采用内部静态类,
只在第一次调用getInstance方法的时候才实例化单例对象
如果不调用,就不会进行单例对象的实例化,
因此,既实现了延迟实例化,又不需要线程同步
引用
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
下面这种就是
还有两种解决方案,不在本帖讨论范围之内
1.采用synchronized的关键字同步getInstance方法
2.采用synchronized的关键字同步代码段,双重是否为空的判断
评论
34 楼
赵精龙
2011-05-18
在哪看过,最好的单例模式是只含一个元素的enum
33 楼
Technoboy
2011-05-18
nianien 写道
[quote="sswh]
[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的
public static void main(String[] args) throws ClassNotFoundException { Class.forName("my.SingleTon", false, Test.class.getClassLoader()); System.out.println("做点其他事情..."); SingleTon.getInstance(); } }
[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的
关于Class.forName对一个类实例化时,static关键字修饰的变量初始化与否与类加载器有关,
默认forName0(className, true, ClassLoader.getCallerClassLoader());
如果为forName0(className, false, ClassLoader.getCallerClassLoader());那么就不会初始化类中的static变量
http://technoboy.iteye.com/blog/1005718
32 楼
nianien
2011-05-18
[quote="sswh]
[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的
public static void main(String[] args) throws ClassNotFoundException { Class.forName("my.SingleTon", false, Test.class.getClassLoader()); System.out.println("做点其他事情..."); SingleTon.getInstance(); } }
[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的
31 楼
nianien
2011-05-18
sswh 写道
nianien 写道
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
“静态代码块执行顺序要晚于静态字段”
这句话不准确。静态代码的初始化顺序取决于 声明的顺序,没有绝对的 静态代码块晚于静态字段。
看下面的代码:
public class InitDemo { static { d1 = new Demo(4); } private static Demo d1 = new Demo(1); static { d1 = new Demo(5); } private static Demo d2 = new Demo(2); public static void main(String[] args) throws ClassNotFoundException { System.out.println(); } } class Demo { public Demo(int count) { System.out.println(count); } }
其实,本质上来说:
private static Demo d1 = new Demo(1);
完全等价于:
private static Demo d1 = null; static { d1 = new Demo(1); }
它们只是两种不同的书写方法而已。不止静态变量,实例变量也是一样。
实例变量的初始化可以以3种形式定义,但编译器编译的时候,会把各种形式的初始化语句按出现顺序放到构造函数中。
public class InitDemo { Map buf = new HashMap(); { buf.put("aaa", "bbb"); } String s2; public InitDemo() { s2 = "ddd"; } }
等价于:
public class InitDemo { Map buf; String s2; public InitDemo() { buf = new HashMap(); buf.put("aaa", "bbb"); s2 = "ddd"; } }
嗯,你说的对,以后得多向你学习了~
30 楼
sswh
2011-05-18
nianien 写道
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
“静态代码块执行顺序要晚于静态字段”
这句话不准确。静态代码的初始化顺序取决于 声明的顺序,没有绝对的 静态代码块晚于静态字段。
看下面的代码:
public class InitDemo { static { d1 = new Demo(4); } private static Demo d1 = new Demo(1); static { d1 = new Demo(5); } private static Demo d2 = new Demo(2); public static void main(String[] args) throws ClassNotFoundException { System.out.println(); } } class Demo { public Demo(int count) { System.out.println(count); } }
其实,本质上来说:
private static Demo d1 = new Demo(1);
完全等价于:
private static Demo d1 = null; static { d1 = new Demo(1); }
它们只是两种不同的书写方法而已。不止静态变量,实例变量也是一样。
实例变量的初始化可以以3种形式定义,但编译器编译的时候,会把各种形式的初始化语句按出现顺序放到构造函数中。
public class InitDemo { Map buf = new HashMap(); { buf.put("aaa", "bbb"); } String s2; public InitDemo() { s2 = "ddd"; } }
等价于:
public class InitDemo { Map buf; String s2; public InitDemo() { buf = new HashMap(); buf.put("aaa", "bbb"); s2 = "ddd"; } }
29 楼
kingkan
2011-05-18
lyy3323 写道
lyy3323 写道
nianien 写道
lyy3323 写道
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
说错,确实是达到延迟加载。只不过看出去有点怪。
呵呵,大家都很热衷技术啊,好现象~
我个人认为带懒加载的最优单例模式是楼主说的第二种,不知大家认为如何。
28 楼
lyy3323
2011-05-18
lyy3323 写道
nianien 写道
lyy3323 写道
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
说错,确实是达到延迟加载。只不过看出去有点怪。
27 楼
lyy3323
2011-05-18
nianien 写道
lyy3323 写道
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
wo kao,刚开始没看清楚,你定义了以个静态的内部类。。。。
你这做法? 通过牺牲初始化内部类达到延迟加载单列类???
26 楼
kingkan
2011-05-18
nianien 写道
引用
Java代码
1.public class SingleTon {
2. private static SingleTon s = new SingleTon();
3.
4. public static SingleTon getInstance() {
5. return s;
6. }
7.
8. static {
9. System.out.println("悲催了,被加载了!");
10. }
11.
12. private SingleTon() {
13. System.out.println("悲催了,被实例化了!");
14. }
15.}
16.
17.public class Test {
18.
19. public static void main(String[] args) throws ClassNotFoundException {
20. Class.forName("my.SingleTon", false, Test.class.getClassLoader());
21. System.out.println("做点其他事情...");
22. SingleTon.getInstance();
23. }
24.}
public class SingleTon {
private static SingleTon s = new SingleTon();
public static SingleTon getInstance() {
return s;
}
static {
System.out.println("悲催了,被加载了!");
}
private SingleTon() {
System.out.println("悲催了,被实例化了!");
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("my.SingleTon", false, Test.class.getClassLoader());
System.out.println("做点其他事情...");
SingleTon.getInstance();
}
}
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
1.public class SingleTon {
2. private static SingleTon s = new SingleTon();
3.
4. public static SingleTon getInstance() {
5. return s;
6. }
7.
8. static {
9. System.out.println("悲催了,被加载了!");
10. }
11.
12. private SingleTon() {
13. System.out.println("悲催了,被实例化了!");
14. }
15.}
16.
17.public class Test {
18.
19. public static void main(String[] args) throws ClassNotFoundException {
20. Class.forName("my.SingleTon", false, Test.class.getClassLoader());
21. System.out.println("做点其他事情...");
22. SingleTon.getInstance();
23. }
24.}
public class SingleTon {
private static SingleTon s = new SingleTon();
public static SingleTon getInstance() {
return s;
}
static {
System.out.println("悲催了,被加载了!");
}
private SingleTon() {
System.out.println("悲催了,被实例化了!");
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("my.SingleTon", false, Test.class.getClassLoader());
System.out.println("做点其他事情...");
SingleTon.getInstance();
}
}
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
这个受教了,但是这个也只是对Class.forName有用吧,
一旦你调用了该类的其他方法或者引用该类信息的时候就会实例化吧?
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。
25 楼
nianien
2011-05-18
sswh 写道
nianien 写道
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
但是,不能实现延迟实例化
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
private static SingleTon s=new SingleTon();
完全等价于:
private static SingleTon s; static { s=new SingleTon(); }
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
public static Class<?> forName(String name, boolean initialize, ClassLoader loader)
声明一下,这里讲延迟加载,就是你不显示call 实例的时候,不会实例化,至于你调其他方法什么的,木有关系
24 楼
nianien
2011-05-18
zhouxianglh 写道
一个静态内部类,纠结甚!
何来纠结,只是讨论延迟加载的问题~
23 楼
nianien
2011-05-18
引用
Java代码
1.public class SingleTon {
2. private static SingleTon s = new SingleTon();
3.
4. public static SingleTon getInstance() {
5. return s;
6. }
7.
8. static {
9. System.out.println("悲催了,被加载了!");
10. }
11.
12. private SingleTon() {
13. System.out.println("悲催了,被实例化了!");
14. }
15.}
16.
17.public class Test {
18.
19. public static void main(String[] args) throws ClassNotFoundException {
20. Class.forName("my.SingleTon", false, Test.class.getClassLoader());
21. System.out.println("做点其他事情...");
22. SingleTon.getInstance();
23. }
24.}
public class SingleTon {
private static SingleTon s = new SingleTon();
public static SingleTon getInstance() {
return s;
}
static {
System.out.println("悲催了,被加载了!");
}
private SingleTon() {
System.out.println("悲催了,被实例化了!");
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("my.SingleTon", false, Test.class.getClassLoader());
System.out.println("做点其他事情...");
SingleTon.getInstance();
}
}
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
1.public class SingleTon {
2. private static SingleTon s = new SingleTon();
3.
4. public static SingleTon getInstance() {
5. return s;
6. }
7.
8. static {
9. System.out.println("悲催了,被加载了!");
10. }
11.
12. private SingleTon() {
13. System.out.println("悲催了,被实例化了!");
14. }
15.}
16.
17.public class Test {
18.
19. public static void main(String[] args) throws ClassNotFoundException {
20. Class.forName("my.SingleTon", false, Test.class.getClassLoader());
21. System.out.println("做点其他事情...");
22. SingleTon.getInstance();
23. }
24.}
public class SingleTon {
private static SingleTon s = new SingleTon();
public static SingleTon getInstance() {
return s;
}
static {
System.out.println("悲催了,被加载了!");
}
private SingleTon() {
System.out.println("悲催了,被实例化了!");
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("my.SingleTon", false, Test.class.getClassLoader());
System.out.println("做点其他事情...");
SingleTon.getInstance();
}
}
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
这个受教了,但是这个也只是对Class.forName有用吧,
一旦你调用了该类的其他方法或者引用该类信息的时候就会实例化吧?
22 楼
kingkan
2011-05-18
sswh,bingo!
可以结贴了。
可以结贴了。
21 楼
zhouxianglh
2011-05-18
一个静态内部类,纠结甚!
20 楼
nianien
2011-05-18
lyy3323 写道
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
真是服了你了,你知道static有哪些用处么?
19 楼
nianien
2011-05-18
sswh 写道
nianien 写道
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
但是,不能实现延迟实例化
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
private static SingleTon s=new SingleTon();
完全等价于:
private static SingleTon s; static { s=new SingleTon(); }
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
public static Class<?> forName(String name, boolean initialize, ClassLoader loader)
静态代码块和静态成员变量加载是有先后顺序的好不好?
public class InitDemo {
private static Demo d1 = new Demo(1);
private static Demo d2 = new Demo(2);
private static Demo d3 = new Demo(3);
static {
d1 = new Demo(0);
d1 = new Demo(0);
d1 = new Demo(0);
}
public static void main(String[] args) throws ClassNotFoundException {
System.out.println();
}
}
class Demo {
public Demo(int count) {
System.out.println(count);
}
}
从测试结果你可以看到,静态代码块执行顺序要晚于静态字段,因此,我们常用静态代码块改写初始值,字段默认初始值为null,执行静态代码块就是改写null值,它并不是最初的赋值
18 楼
sswh
2011-05-18
nianien 写道
引用
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
这种方式下的确 是延迟到getInstance()方法被调用的时候才实例化new SingleTon();
nianien 写道
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
但是,不能实现延迟实例化
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种方式下new SingleTon();是在SingleTon类被加载的时候才初始化的,SingleTon类被加载的时机是
该类第一次被引用的时候。所以,什么时候加载不确定。
但一般引用SingleTon类的代码被执行的时候,也就是需要使用的时候了,所以实质上也有延迟的效果。
比如下面的代码:
public class SingleTon { private static SingleTon s = new SingleTon(); public static SingleTon getInstance() { return s; } static { System.out.println("悲催了,被加载了!"); } private SingleTon() { System.out.println("悲催了,被实例化了!"); } } public class Test { public static void main(String[] args) throws ClassNotFoundException { Class.forName("my.SingleTon", false, Test.class.getClassLoader()); System.out.println("做点其他事情..."); SingleTon.getInstance(); } }
Test类main方法的第一行加载SingleTon类,但不会初始化SingleTon。
SingleTon类被初始化是 直到调用SingleTon.getInstance();方法的时候。
所以,这种方法也是具有延迟加载效果的。
17 楼
lyy3323
2011-05-18
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
static是什么?哪来的延迟。
16 楼
sswh
2011-05-18
nianien 写道
下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
但是,不能实现延迟实例化
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s=new SingleTon();
public static SingleTon getInstance() {
return s;
}
}
这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用
public class SingleTon {
private SingleTon(){}
private static SingleTon s;
static {
s=new SingleTon();
}
public static SingleTon getInstance() {
return s;
}
}
上下两份代码编译后的字节码一模一样,
何来上面一种“但是,不能实现延迟实例化”
而下面一种“虽然能够延迟单例对象的实例化”
也就是说:
private static SingleTon s=new SingleTon();
完全等价于:
private static SingleTon s; static { s=new SingleTon(); }
静态变量的初始化发生在 类被加载的时候(缺省情况下,被加载的类会在加载时被初始化,除非明确指定延迟初始化),
public static Class<?> forName(String name, boolean initialize, ClassLoader loader)
15 楼
nianien
2011-05-18
zhang34082 写道
nianien 写道
zhang34082 写道
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的"
怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的
类加载的时候,对于静态变量与块,从上而下逐个执行。延迟加载是用的时候才实例化。
public static void main(String[] args) {
SingleTon instance = SingleTon .getInstance();// 在这个地方设断点
}
可以通过这个在测试。是否是延迟加载的
public class SingleTon {
private SingleTon(){}
public static SingleTon getInstance() {
return SingleTonHolder.instance;
}
static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}
你敢实际测试一下么?
你不调用,它会实例化?
多的俺不说了,如果你觉得他是延迟加载的,你提供测试方法出来,或者说下静态类、嵌套类中静态实例在类加载的时候是怎么加载的
测试结果出来了,你还有什么话说?
唉,眼高手低的人~~~~~~
相关推荐
**设计模式——单例模式** 在软件工程中,设计模式是一种在特定场景下解决常见问题的标准方案,可以被复用并提升代码质量。单例模式是设计模式中的一种,它保证一个类只有一个实例,并提供一个全局访问点。这种模式...
总的来说,单例模式是一种常见的设计模式,懒汉式单例模式则是其中一种实现策略,它的主要特点是延迟加载和线程安全。在选择单例模式实现时,开发者需要根据具体需求考虑性能、线程安全以及代码简洁性等因素。
在本文中,我们将深入探讨三种工厂设计模式——简单工厂模式、抽象工厂模式和工厂方法模式,以及两种单例模式——饿汉单例模式和懒汉单例模式。这些模式都是面向对象设计中的重要组成部分,对于理解和构建可维护、可...
非线程安全的懒汉模式代码如下: ```java public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { ...
Python中的线程同步机制是为了在多线程环境中确保对共享资源的有序访问,避免出现竞态条件和数据不一致的情况。在上述例子中,我们看到了一个典型的线程同步问题及其解决方案。 首先,让我们理解什么是线程竞态条件...
这种同步的懒汉式虽然保证了线程安全,但在多线程环境下,每次获取实例都需要进行同步,性能会受到影响。 为了兼顾线程安全和性能,可以采用双检锁/双重校验锁(Double-Check Locking,DCL)的懒汉式单例: ```...
文件系统本质上是一个大型的单例模式实现,确保了所有文件操作都在同一套规则下执行,从而保障了数据的完整性和安全性。 **9. HttpApplication** 在ASP.NET框架中,HttpApplication作为HTTP请求处理流程的核心组件...
**设计模式——单例模式** 单例模式是一种广泛应用于软件设计中的创建型设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处在于控制共享资源的访问,比如线程安全的数据库连接池...
视频课程下载——C#多线程与线程同步机制高级实战课程
为了使"懒汉式"单例在多线程环境下安全,可以使用synchronized关键字来同步方法: ```java public class Singleton { private static Singleton instance; private Singleton() {} public synchronized static ...
- **并发问题**:在多线程环境中,单例模式可能会导致线程安全问题,需要额外处理同步机制。 #### 五、实例解析 在给定的内容中提到的`Martin`类就是一个典型的单例模式实现案例。它通过将构造器私有化以及提供一...
另一种线程安全且高效的单例实现方式是利用Java类加载机制,将实例的创建推迟到类加载时: ```java public class SingletonClass { private SingletonClass() {} private static class SingletonHolder { ...
然而,普通的懒汉式单例在多线程环境下可能存在线程安全问题,即多个线程可能同时进入`if (null == beautifulSister)`判断并创建多个实例。 为了解决这个问题,可以使用双重检查锁定(Double-Checked Locking)来...
在上述代码中,`getInstance()`方法使用了双重检查锁定,既保证了线程安全,又避免了不必要的同步开销。 结合工厂模式和单例模式,我们可以设计出更复杂的应用架构。例如,一个系统中可能有多个单例对象,每个对象...
4. 懒汉式(线程安全——同步方法) 通过同步关键字`synchronized`保证线程安全,但每次获取实例时都需要进行同步操作,性能较低。 ```java public class Singleton { private static Singleton instance; ...
在这个例子中,`volatile`关键字确保了多线程环境下的可见性和有序性,`synchronized`关键字确保了线程安全,避免了多个线程同时创建单例对象。 接下来,我们转向“装饰模式”。装饰模式是一种结构型设计模式,它...
实验内容集中在Linux下的多线程同步机制上,具体通过修改生产者-消费者问题的示例程序来实现。在这个问题中,多个生产者线程生成数据,而消费者线程负责消费这些数据。为了保证数据的一致性和正确性,需要防止多个...
【Java设计模式——单例模式】 单例模式是一种常见的软件设计模式,它的核心思想是确保在应用程序的整个生命周期中,某个类只有一个实例存在。这种模式主要用于控制类的实例化过程,减少系统资源的消耗,提高系统...