四.反射的定义
反射的定义:
反射即反向探知。
java反射指程序运行状态中
- 给定一个类(Class)对象,通过反射获取这个类(Class)对象的所有成员结构(属性和方法);
- 给你一个具体对象,动态调用方法及对任意属性值进行获取和赋值;
这种动态获取类的内容、创建对象、动态调用对象的方法及操作属性的机制叫java的反射机制
优势:
- 增加程序的灵活性,避免将固有逻辑程序写死在代码中;
- 代码简洁,可读性强,提高代码的复用率;
缺点:
- 性能下降;
- 存在内部暴露和安全隐患;
反射慢在哪里?
1、调用了native方法。
2、反射的newInstance使用了JNI技术,方法内有检查权限与安全导致性能下降。
二、反射内部
Class类
1.获取类对象的四种方式
new Parent().getClass();
Parent.class;
Class.forName("com.demo.Parent");
ReflectDemo.class.getClassLoader().loadClass("com.demo.Parent");
2.基本操作
getModifiers() 返回数字对应含义(来自java API)
3.字段操作
public class Parent {
private String bb;
.....
Parent p = new Parent();
Field field = p.getClass().getDeclaredField("bb");
field.set(p, "aaaa");
System.out.println(p.getBb());
字段权限不足(private),不能操作。
Parent p = new Parent();
Field field = p.getClass().getDeclaredField("bb");
field.setAccessible(true); 如果字段是私有属性,放开权限
field.set(p, "aaaa");
System.out.println(p.getBb());
4.类中的方法
1.1.6反射进阶–单例也许并不单例
单例模式:
- 私有化构造函数;
- 全局唯一的公有访问点
通过反射机制可以破坏单例模式
产生原因:反射可以调用私有的构造器。
public class Simgle {
private static Simgle simgle;
public Simgle() {
}
public static Simgle getInstance() {
if (simgle == null) {
simgle = new Simgle();
}
return simgle;
}
public static void main(String[] args)throws Exception {
Simgle simgle1 = Simgle.getInstance();
Simgle simgle2 = Simgle.getInstance();
Simgle simgle3 = Simgle.getInstance();
System.out.println(simgle1);
System.out.println(simgle2);
System.out.println(simgle3);
Constructor[] constructors = simgle1.getClass().getConstructors();
for(Constructor c : constructors){
System.out.println(c.newInstance());
}
}
}
结果:
堵漏洞:(让单例不能被反射调用构造器而被破坏)
方法:在构造函数中判断类是否有实例:
public Simgle() {
if (simgle != null) {
throw new RuntimeException("已有实例,请勿重复创建");
}
}
结果:
1.1.7 反射的升华-SpringIOC容器
IOC(Inversion of Control)
控制反转,一种设计思想,非实际的技术,核心思想实际将预先设计好的对象实例创建的控制权交给程序(IOC容器)。
IOC容器的本质是一个K-V结构的map
Q:Spring的IOC容器如何做到控制反转?