先贴几个比较全的java反射博客
Java反射:用最直接的大白话来聊一聊Java中的反射机制Java基础之—反射(非常重要)Java反射技术详解
前面介绍的单例模式的实现方式: 设计模式之单例模式
单例模式的设计在于只保留一个公有静态函数来获取唯一的实例 , 其他方法(构造函数)或字段为私有 , 外界不能访问 。
而java反射则突破了构造函数私有的限制 , 可以获取单例类的私有构造函数并使用 。
//得到该类在内存中的字节码对象Class objectClass = Class.forName("com.xt.designmode.creational.singleton.hungryBoyClass.Singleton");//获取构造器Constructor constructor = objectClass.getDeclaredConstructor();//暴力反射 , 解除私有限定constructor.setAccessible(true);Singleton reflectInstance = (Singleton) constructor.newInstance();
我们针对所有实现单例模式的方法使用如下测试
public class ReflectTest {public static void main(String[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {Class objectClass = Class.forName("com.xt.designmode.creational.singleton.hungryBoyClass.Singleton");Constructor constructor = objectClass.getDeclaredConstructor();constructor.setAccessible(true);Singleton instance = Singleton.getInstance();Singleton reflectInstance = (Singleton) constructor.newInstance();System.out.println(instance);System.out.println(reflectInstance);//对象类型 , == 比较的是地址if(instance != reflectInstance){System.out.printf("创建了两个实例\n");}else{System.out.printf("只创建了一个实例\n");}}}
除开枚举式实现的单例模式 , 其余的方式都可以被反射直接获取到私有的构造器来创建新实例 。
我们先看看枚举类是怎样防御反射攻击的 。
像我 设计模式之单例模式这篇博客实现的枚举类实现单例是不能抵抗反射攻击的 , 因为我们不反射枚举类 , 直接反射类就可以了 , 并且因为类的构造函数是的 , 所以真想攻击的话 , 直接去new 实例就好了 。(逃
public enum Singleton {INSTANCE;private Resource resource;private Singleton(){resource = new Resource();}public Resource getInstance(){return resource;}}
我们采用如下形式enum 枚举类实现单例模式
public enum EnumSingleton {INSTANCE;private EnumSingleton(){}public static EnumSingleton getInstance() {return INSTANCE;}}
测试
public class ReflectTest {public static void main(String[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {Class objectClass = Class.forName("com.xt.designmode.creational.singleton.destroy.EnumSingleton");Constructor constructor = objectClass.getDeclaredConstructor();constructor.setAccessible(true);//枚举类式的单例模式EnumSingleton instance = EnumSingleton.INSTANCE;EnumSingleton reflectInstance = (EnumSingleton) constructor.newInstance();if(instance != reflectInstance){System.out.printf("创建了两个实例\n");}else{System.out.printf("只创建了一个实例\n");}}}
会报出找不到无参的构造方法的异常 。这个问题多个博主也遇到过 , 通过反编译的方式找到了问题所在 。
我们使用javac来对代码进行编译,使用jad工具对class代码进行反编译
javac工具读由java语言编写的类和接口的定义 , 并将它们编译成字节代码的class文件
- 8种 单例设计模式
- 钱某、韩某,破坏军婚,双双获刑! 中国十大军人犯罪案例
- 大渣男32年结婚105次,创下吉尼斯世界纪录 男人破坏吉尼斯记录
- 全民奇迹5转可以拿几阶,全民奇迹剑士五转多少级可以拿破坏
- 人类历史上曾出现过这样一次灾难,破坏力远胜瘟疫、海啸和战争 历史之最自然灾害
- 破坏神是什么?
- 什么是破坏版,暗黑破坏神2单机版死灵法师加点
- 内爆夺命5人,死者中惊现泰坦尼克当年遇难者的玄孙女丈夫 男子破坏吉尼斯记录
- 泰坦“魔咒” 破坏吉尼斯记录
- 一代天骄成吉思汗是怎样从破坏者到庇护者的