终结者单身——setAccessible(true)
首先看一下“传说”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)的更多相关文章
- Java 反射 getDeclareFields getModifiers setAccessible(true)
示例代码: public static Map<String, Object> dtoToMap(Object obj, String pre, String las ...
- field.setAccessible(true) 简介
今天查看别人写的代码时,发现这样一句代码,顿时来了兴趣. 需要注意setAccessible 并不是在Field中的,而是在AccessibleObject中. 下面是AccessibleObject ...
- 提高java反射速度的方法method.setAccessible(true)
转载:http://huoyanyanyi10.iteye.com/blog/1317614 提高java反射速度的方法method.setAccessible(true) package com.c ...
- [转载] 在java中为什么变量1000 = 1000 返回false,但是100=100返回true?
ps:题目的意思是指定义相同内容的不同变量之间的==比较.如果直接比较(100 == 100)的结果是true. 运行以下代码: Integer a = 1000, b = 1000; System. ...
- 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 ...
- Java 反射 调用私有域和方法(setAccessible)
Java 反射 调用私有域和方法(setAccessible) @author ixenos AccessibleObject类 Method.Field和Constructor类共同继承了Acces ...
- 为什么Java 两个Integer 中1000==1000为false而100==100为true?
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt346 这是一个挺有意思的讨论话题. 如果你运行下面的代码 1 2 3 4 I ...
- 反射setAccessible()方法
java代码中,常常将一个类的成员变量置为private 在类的外面获取此类的私有成员变量的value时,需要注意: 测试类: public class AccessibleTest { privat ...
- 奇怪的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 = ...
随机推荐
- JavaScript RegExp对象
一.什么是RegExp 1.RegExp 是正則表達式的缩写. 2.当您检索某个文本时,能够使用一种模式来描写叙述要检索的内容.RegExp 就是这样的模式. 3.简单的模式能够是一个 ...
- Storm-0.9.2-incubating源代码编译打包
近期遇到一些同学询问Storm-0.9.2-incubating源代码编译打包的问题,现将编译步骤说明例如以下: 1.凝视掉project各pom文件里关于maven插件(maven-gpg-plug ...
- 【Java探索道路安全系列:Java可扩展的安全架构】一间:Java可扩展的安全体系结构开始
笔者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...
- Debian7.6安装过程中遇到的问题
一 sudo命令不能用 1 使用su切换到root用户,命令: su 2 使用名:vim /etc/sudoers加入sudoer用户,命令: vim /etc/sudoers 找到root=(ALL ...
- ubuntu 搭建svn服务器
1.安装Subversion sudo apt-get install subversion 2.创建资源库 cd /home/username/ svnserve -d -r /home/usern ...
- 在Java中如何使用jdbc连接Sql2008数据库(转)
我们在javaEE的开发中,肯定是要用到数据库的,那么在javaEE的开发中,是如何使用代码实现和SQL2008的连接的呢?在这一篇文章中,我将讲解如何最简单的使用jdbc进行SQL2008的数据库的 ...
- java-IO操作性能对照
在软件系统中.IO速度比内存速度慢,IO读写在非常多情况下会是系统的瓶颈. 在java标准IO操作中,InputStream和OutputStream提供基于流的IO操作.以字节为处理单位:Reade ...
- BZOJ 3531: [Sdoi2014]旅游
职务地址:http :// www . lydsy . com / JudgeOnline / problem . php ? id = 3531 标题效果:看到原来的标题. 算法讨论:树链拆分. 就 ...
- 去掉word中向下的箭头^l----->^p
去掉word中向下的箭头 在网页上复制文章到word中,会发现有很多向下的箭头,这些 符号叫做软回车符.如何去掉这些向下的箭头呢.步骤如下: 方法/步骤 按Ctrl+H,弹出全局替换窗口,输入查找内容 ...
- windows phone (15) UI变换上
原文:windows phone (15) UI变换上 在wp中只要是继承自UIElement 的任何对象都可以应用变换,当然包含Textblock,Rectangle等所有的元素,下面我们使用Tex ...