首先看一下“传说”Singleton模式

package go.derek;

public class Singleton{

	public static int times;
private Singleton(){
//构造器被调用的时候会打印出次数
System.out.println("单例构造器被调用"+(++times)+"两次");
} private final static Singleton instance=new Singleton(); public static Singleton getInstance(){
return instance;
} public void doSomething(){
System.out.println("do something");
} }

以下是測试类主函数:

package go.derek;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//通过单例模式获得单例对象obj1
Singleton obj1=Singleton.getInstance();
//运行一次doSomething方法
obj1.doSomething();
//观察控制台,这次获得的obj2对象跟obj1是同一个单例。没有调用构造器
Singleton obj2=Singleton.getInstance();
obj2.doSomething();
//以下厉害的来了,首先拿到万能的Class对象
Class<Singleton> clazz=Singleton.class;
//然后拿到构造器。使用这种方法私有的构造器也能够拿到
Constructor<Singleton> c=clazz.getDeclaredConstructor();
//设置在使用构造器的时候不运行权限检查
c.setAccessible(true);
//因为没有了权限检查。所以在Singleton类外面也能够创建对象了,然后运行方法
//观察控制台,私有构造器又被调用了一次,单例模式被攻陷了,运行方法成功。 c.newInstance().doSomething();
}
}

执行结果例如以下:

单例构造器被调用1两次

do something

do something

单例构造器被调用2两次

do something

试想一下,假设某个恶意client通过上面的方式。就能够为所欲为了。所以为了避免出现这样的情况,能够再构造器被第二次调用的时候抛出一个异常

package go.derek;

public class Singleton{

	public static int times;
private Singleton() {
//构造器被调用的时候会打印出次数
System.out.println("单例构造器被调用"+(++times)+"两次");
if(instance!=null){
throw new IllegalArgumentException("单例构造器不能反复使用");
}
} private final static Singleton instance=new Singleton(); public static Singleton getInstance(){
return instance;
} public void doSomething(){
System.out.println("do something");
} }

执行结果例如以下:

单例构造器被调用1两次

do something

do something

单例构造器被调用2两次

Exception in thread "main" java.lang.reflect.InvocationTargetException

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

at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

at java.lang.reflect.Constructor.newInstance(Constructor.java:526)

at go.derek.Test.main(Test.java:24)

Caused by: java.lang.IllegalArgumentException: 单例构造器不能反复使用

at go.derek.Singleton.<init>(Singleton.java:10)

... 5 more

目标实现~

版权声明:本文博客原创文章,博客,未经同意,不得转载。

终结者单身——setAccessible(true)的更多相关文章

  1. Java 反射 getDeclareFields getModifiers setAccessible(true)

    示例代码: public static Map<String, Object> dtoToMap(Object obj, String pre,            String las ...

  2. field.setAccessible(true) 简介

    今天查看别人写的代码时,发现这样一句代码,顿时来了兴趣. 需要注意setAccessible 并不是在Field中的,而是在AccessibleObject中. 下面是AccessibleObject ...

  3. 提高java反射速度的方法method.setAccessible(true)

    转载:http://huoyanyanyi10.iteye.com/blog/1317614 提高java反射速度的方法method.setAccessible(true) package com.c ...

  4. [转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?

    ps:题目的意思是指定义相同内容的不同变量之间的==比较.如果直接比较(100 == 100)的结果是true. 运行以下代码: Integer a = 1000, b = 1000; System. ...

  5. Java中1000==1000为false而100==100为true

    public static void main(String[] args) { int z1 = 0; int z2 = 0; System.out.println(z1==z2);//TRUE I ...

  6. Java 反射 调用私有域和方法(setAccessible)

    Java 反射 调用私有域和方法(setAccessible) @author ixenos AccessibleObject类 Method.Field和Constructor类共同继承了Acces ...

  7. 为什么Java 两个Integer 中1000==1000为false而100==100为true?

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt346 这是一个挺有意思的讨论话题. 如果你运行下面的代码 1 2 3 4 I ...

  8. 反射setAccessible()方法

    java代码中,常常将一个类的成员变量置为private 在类的外面获取此类的私有成员变量的value时,需要注意: 测试类: public class AccessibleTest { privat ...

  9. 奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?

    如果你运行如下代码: 1 2 3 4 Integer a = 1000, b = 1000;  System.out.println(a == b);//1 Integer c = 100, d =  ...

随机推荐

  1. C#List<long>与String(Linq)

    1.string => List<long> string ShopIds = "1,2,3"; var ShopIdList = ShopIds.Split(' ...

  2. Python数据结构-元祖

    print()) print() #等价于: print('Tom is %d'%(5))

  3. 从后台绑定数据到ligerui 的comboBox下拉框组件

    这次来记录一下ligerUI的comboBox下拉框组件,ligerUI的API里也有相关描写叙述,上面都是前台写死数据,然后显示在组件中,我这次要说的是将后台的数据绑定到下拉框组件中,废话不多说. ...

  4. POJ1470 Closest Common Ancestors 【Tarjan的LCA】

    非常裸的模版题,只是Tarjan要好好多拿出来玩味几次 非常有点巧妙呢,tarjan,大概就是当前结点和它儿子结点的羁绊 WA了俩小时,,,原因是,这个题是多数据的(还没告诉你T,用scanf!=EO ...

  5. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

  6. 用KnockoutJS实现ToDoMVC代码分析

    体验地址 Knockout 版todo web app在线体验 http://todomvc.com/examples/knockoutjs/ 源码地址 项目源码地址,此地址包含了各种JS框架实现的t ...

  7. tar解压出错

    现象 # tar -zxvf aaa.tar.gz tar: This does not look like a tar archive tar: Skipping to next header ta ...

  8. html中滚动栏的样式

    DIV滚动栏设置 (CSS)2008/09/26 03:07div 中滚动栏的控制2008年01月06日 星期日 01:181)隐藏滚动栏<body style="overflow-x ...

  9. HttpDNS 服务详解(转)

    但凡使用域名来给用户提供服务的互联网企业,都或多或少地无法避免在有中国特色的互联网环境中遭遇到各种域名被缓存.用户跨网访问缓慢等问题.那么对于腾讯这样的域名数量在10万级别的互联网公司来讲,域名解析异 ...

  10. 矩形旋转碰撞,OBB方向包围盒算法实现

    怎样进行2D旋转矩形的碰撞检測.能够使用一种叫OBB的检測算法(Oriented bounding box)方向包围盒.这个算法是基于SAT(Separating Axis Theorem)分离轴定律 ...