java 反射机制更改私有属性 重复创建单例类对象

单例类:

 

 

package com.shenli.test;

public class Singleton {

	private static final Singleton singleton = new Singleton();
	
	private Singleton(){}
	
	
	public static Singleton getInstance(){
		return singleton;
	}
	
	private int intValue = -1;
	
	public int getIntValue(){
		return this.intValue;
	}
	
	@Override
	public String toString() {
		return String.valueOf(hashCode()).concat(",").concat(String.valueOf(intValue));
	}
}

 

 

 

它是一个单例类,并且拥有一个私有属性intValue,现在我们使用反射机制来改变私有属性,并且创建新的实例对象:

 

 

package com.shenli.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestReflect {

	
	public static void main(String[] args) {
		Singleton s = Singleton.getInstance();
		
		
		Singleton s2 = Singleton.getInstance();
		System.out.println("before change private value.");
		System.out.println("\t s:"+s+",\n\t s2:"+s2);
		
		
		Class clazz = Singleton.class;
		
		Field field;
		try {
			field = clazz.getDeclaredField("intValue");
			field.setAccessible(true);
			field.setInt(s2, 100);
		} catch (NoSuchFieldException | SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
			
		
		
		
		System.out.println("\n After use reflect change private:");
		System.out.println("\t s:"+s+",\n\ts2:"+s2);
		
		
		try {
			Constructor<Singleton>[] constructors = clazz.getDeclaredConstructors();
			for(Constructor<Singleton> constructor : constructors){
				constructor.setAccessible(true);
				Singleton s3 = constructor.newInstance();
				System.out.println("\n After use reflect change constructor.");
				System.out.println("\t s:"+s+",\n\t s2:"+s2+"\n\t s3:"+s3);
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
		
		System.out.println("\nSo the private value can be change, \nand Singleton object can be Re-created.");
	}
}

 

 

输出:

 

 

before change private value.

s:1143701442,-1,

s2:1143701442,-1

 

 After use reflect change private:

s:1143701442,100,

s2:1143701442,100

 

 After use reflect change constructor.

s:1143701442,100,

s2:1143701442,100

s3:1956785676,-1

 

So the private value can be change, 

and Singleton object can be created many times.

 

 

如果不希望私有属性被更改,可以声明为final

如果单例类不会重复创建,就要在私有构造函数里面抛出异常。

更改后的Singleton如下:

 

package com.shenli.test;

public final class Singleton {

	private static final Singleton singleton = new Singleton();
	
	private Singleton(){
		if(singleton != null){
			throw new RuntimeException("The class Singleton can not be re-created!");
		}
	}
	
	
	public static Singleton getInstance(){
		return singleton;
	}
	
	private final int intValue = -1;
	
	public int getIntValue(){
		return this.intValue;
	}
	
	@Override
	public String toString() {
		return String.valueOf(hashCode()).concat(",").concat(String.valueOf(intValue));
	}
}
 

运行测试程序后的输出:

 

before change private value.

s:64011397,-1,

s2:64011397,-1

 

 After use reflect change private:

s:64011397,-1,

s2:64011397,-1

 

java.lang.reflect.InvocationTargetException

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)

at java.lang.reflect.Constructor.newInstance(Unknown Source)

at com.shenli.test.TestReflect.main(TestReflect.java:46)

Caused by: java.lang.RuntimeException: The class Singleton can not be re-created!

at com.shenli.test.Singleton.<init>(Singleton.java:9)

... 5 more


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值