java反射技术破坏单例模式

 一、 Java中的反射技术可以获取类的所有方法、成员变量、还能访问private的构造方法,这样一来,单例模式中用的私有构造函数被调用就会产生多个实例,编写代码测试一下。

package test;

import java.lang.reflect.Constructor;

public class SingetonTest {

	private static SingetonTest singleton = null;
	private int s = 0;
	
	// 构造方法是私有的
	private SingetonTest(){}
	
	// 同步的获取实例方法
	public static synchronized SingetonTest getInstance(){
		// 懒汉模式的单例方法
		if(null == singleton){
			singleton = new SingetonTest();
		}
		return singleton;
	}
	
	
	public int getS() {
		return s;
	}

	public void setS(int s) {
		this.s = s;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Constructor con = SingetonTest.class.getDeclaredConstructor();
			con.setAccessible(true);
			// 通过反射获取实例
			SingetonTest singetonTest1 = (SingetonTest)con.newInstance();
			SingetonTest singetonTest2 = (SingetonTest)con.newInstance();
			// 常规方法获取实例
			SingetonTest singetonTest3 = SingetonTest.getInstance();
			SingetonTest singetonTest4 = SingetonTest.getInstance();
			// 测试输出
			System.out.println("singetonTest1.equals(singetonTest2) :" +  singetonTest1.equals(singetonTest2));
			System.out.println("singetonTest3.equals(singetonTest4) :" +  singetonTest3.equals(singetonTest4));
			System.out.println("singetonTest1.equals(singetonTest3) :" +  singetonTest1.equals(singetonTest3));
			singetonTest1.setS(1);
			singetonTest2.setS(2);
			singetonTest3.setS(3);
			singetonTest4.setS(4);
			System.out.println("1:" + singetonTest1.getS() + "  2:" + singetonTest2.getS()+ "  3:" + singetonTest3.getS()+ "  4:" + singetonTest4.getS());
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

测试结果:

singetonTest1.equals(singetonTest2) :false
singetonTest3.equals(singetonTest4) :true
singetonTest1.equals(singetonTest3) :false
1:1  2:2  3:4  4:4

通过反射技术生成的两个实例不同,通过常规方法获取的两个实例相同(即同一个实例,单例)。


二、防止反射破坏单例模式,构造函数调用时进行处理,当构造函数第2次被调用时抛出异常!修改构造方法如下:

private static boolean flag = false;
	
	// 构造方法是私有的
	private SingetonTest(){
		if(flag){
			flag = !flag;
		}
		else{
			try {
				throw new Exception("duplicate instance create error!" + SingetonTest.class.getName());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

三、一些思考

1)单例模式是为了保证一个类只有一个实例,整个系统只能有自己创建的一个实例。应用在数据库连接或单个队列处理等问题。

2)单例模式构造,懒汉模式以时间换空间(用的时候才生产实例,每次都判断);懒汉模式以空间换时间,直接创建实例,以后不用判断直接用。

3)懒汉模式线程安全问题,获取实例的方法要加上synchronized进行同步。

4)java的反射技术不要用于实例创建,反射主要用于Spring的IOC, Hibernate和白盒测试。

 

评论 10 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

lws332969674

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值