单例模式的标准写法

众所周知,一般使用java实现单例模式有两种方法,分别为饿汉式和饱汉式,饿汉式就是在声明时即创建,这样在类加载时就已经创建好了,即时我们可能并不不需要它,它的生命周期是永久的,造成内存泄漏的可能!第二种方式是lazy的,只有在使用时创建,实现了延迟加载。代码为

1.饿汉式

?
1
2
3
4
5
6
7
8
class Singleton {
     private final static Singleton instance = new Singleton();
     private Singleton(){
     }
     public static Singleton getInstance() {
         return instance;
     }
}

2. 饱汉式(双重加锁式)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton {
     private volatile static Singleton instance = null ;
     private Singleton(){
 
     }
     public static Singleton getInstance() {
         if (instance == null ) {
             synchronized (Singleton. class ) {
                 if (instance == null ) {
                     instance = new Singleton();
                 }
             }
         }
         return instance;
     }
}

还有一种方法是使用内部类的方法,这主要为克服方法1中的问题,既能实现延迟加载,又能保证线程安全,而且性能不错。代码为:

?
1
2
3
4
5
6
7
8
9
10
11
class Singleton {
     private Singleton() {
 
     }
     private static class Holder {
         private static final Singleton INSTANCE = new Singleton();
     }
     public static Singleton getInstance() {
         return Holder.INSTANCE;
     }
}

以上方法都是通过使用private构造方法来阻止外部直接创建对象,但如果使用反射机制,则不能保证实例的唯一性了!!!

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class SingletonDemo {
     //@SuppressWarnings("unchecked")
     //public static <T> T newInstance(Class<?> cl) {
     //    T t = null;
     //    try {
     //        t = (T)cl.newInstance(); /* 只能调用public构造方法 */
     //    } catch(Exception e) {
     //        e.printStackTrace();
     //    }
     //    return t;
     //}
     @SuppressWarnings ( "unchecked" )
     public static <T> T newInstance(Class<?> cl) {
         T t = null ;
         try {
             Constructor<?> constructor = cl.getDeclaredConstructor();
             constructor.setAccessible( true );
             t = (T)constructor.newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return t;
     }
     @SuppressWarnings ( "unchecked" )
     public static <T> T newInstance(Class<?> cl, Class<?>...args) {
         T t = null ;
         try {
             Constructor<?> constructor = cl.getDeclaredConstructor(args);
             constructor.setAccessible( true );
             t = (T)constructor.newInstance( "name" , 1 );
         } catch (Exception e) {
             e.printStackTrace();
         }
         return t;
     }
     public static void main(String[] args) {
         Singleton instance = Single.INSTANCE;
         Singleton s1 = newInstance(Singleton. class , String. class , int . class );
         Singleton s2 = newInstance(Singleton. class , String. class , int . class );
         //Tmp t1 = newInstance(Tmp.class);
         //Tmp t2 = newInstance(Tmp.class);
         //System.out.println(s1 == s2);
         //System.out.println(t1 == t2);
     }
}

Joshua Bloch (Effect java 作者)提出一种新的方法实现单例模式,就是使用Enum(其实也是类,一种特殊的类,构造方法必须是private ,final的)!如下:

 

?
1
2
3
4
5
6
enum Singleton {
     INSTANCE;
     public void sayHi() {
         System.out.println( "Hi" );
     }
}

这样当试图通过反射机制创建对象时,会抛出异常!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值