抵御反射机制调用单例类私有构造器

Java 单例模式一般有两种实现:

    1.暴露静态final字段

Java代码 
  1. public class Elvis {  
  2.   
  3.     public static final Elvis INSTANCE = new Elvis();  
  4.       
  5.     private Elvis(){;;;}  
  6.       
  7.     public void leaveTheBuilding() {;;;}  
  8.   
  9. }  

 

  2.暴露静态方法

Java代码 
  1. public class Elvis {  
  2.   
  3.     private static final Elvis INSTANCE = new Elvis();  
  4.       
  5.     private Elvis(){;;;}  
  6.       
  7.     public static Elvis getInstance() { return INSTANCE;}  
  8.     public void leaveTheBuilding() {;;;}  
  9.   
  10. }  

 

    如果借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器,抵御这种方法可以在创建第二次构造器时抛出异常来解决。

 

    自定义异常:

Java代码 
  1. public class InitializationException extends RuntimeException {  
  2.   
  3.     /** 
  4.      *  
  5.      */  
  6.     private static final long serialVersionUID = 1L;  
  7.   
  8.     public InitializationException(String msg) {  
  9.         super(msg);  
  10.     }  
  11. }  

 

    单例类:

Java代码 
  1. public class Singleton {  
  2.   
  3.     private static int count = 0;  
  4.     private static final Singleton INSTANCE = new Singleton();  
  5.       
  6.     private Singleton() {  
  7.         if(count == 1)   
  8.             throw new InitializationException("只能初始化一次!");  
  9.         count++;  
  10.     }  
  11.       
  12.     public static Singleton getInstance() {  
  13.         return INSTANCE;  
  14.     }  
  15. }  

 

    测试类:

Java代码 
  1. public class Test {  
  2.   
  3.     public static void main(String[] args) throws Exception{  
  4.           
  5.         Singleton s1 = Singleton.getInstance();  
  6.         Singleton s2 = Singleton.getInstance();  
  7.           
  8.         System.out.println(s1 == s2);   // 返回 true  
  9.           
  10.         // 试图通过反射机制创建实例  
  11.         for(Constructor<?> c : s1.getClass().getDeclaredConstructors()) {  
  12.             c.setAccessible(true);  // AccessibleObject  
  13.             Singleton s3 = (Singleton)c.newInstance();  
  14.         }  
  15.     }  
  16. }  

 

    抛出的异常:

Console代码 
  1. Exception in thread "main" java.lang.reflect.InvocationTargetException  
  2.     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)  
  3.     at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)  
  4.     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)  
  5.     at java.lang.reflect.Constructor.newInstance(Unknown Source)  
  6.     at org.reflect.Test.main(Test.java:17)  
  7. Caused by: org.reflect.InitializationException: 只能初始化一次!  
  8.     at org.reflect.Singleton.<init>(Singleton.java:10)  
  9.     ... 5 more  

原文:http://blog.youkuaiyun.com/czjuttsw/article/details/8514989

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值