- 什么是反射
反射作为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力,通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性
- 反射的应用场景
平时大部分时候都是在写业务代码,很少会接触到直接使用反射机制的场景。但是,这不代表反射没有用。相反,正是因为反射,你才能轻松地使用各种框架。像Spring/SpringBoot和Mybatis等等框架中,都是大量使用了反射机制。
这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。
public class DebugInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public DebugInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("before method " + method.getName());
Object result = method.invoke(target, args);
System.out.println("after method " + method.getName());
return result;
}
}
另外Java中的一大利器注解的实现也用到了反射。
为什么你使用Spring的时候,一个@Component注解就声明了一个类为Spring Bean呢?为什么你通过@Value注解就可以读取到配置文件中的值呢?
这些都是因为你可以基于反射分析类,然后获取到类/属性/方法/方法的参数上的注解,你获取到注解后,就可以做进一步的处理。
- 谈谈反射机制的优缺点
优点:可以让我们的代码更加的灵活、各种框架提供开箱即用的便利
缺点:让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。比如可以无视泛型参数的安全检查。另外,反射的性能也要稍差点,不过,对应框架来说实际是影响不大的。
获取Class对象的四种方式
如果我们动态获取到这些信息,我们需要依靠Class对象,Class类对象将一个类的方法,变量等信息告诉运行的程序。Java提供了四种方式获取Class对象
- 知道具体类的情况下可以使用:
Class alunbarClass1 = TargetObject.class;
2.通过Class.forName()传入类的全路径获取:
Class alunbarCalss2 = Class.forName("cn.javaguide.TargetObject");
3.通过对象实例instance.getClass()获取:
TargetObject o =new TargetObject();
Class alunbarClass3 = o.getClass();
4.通过类加载器xxxClassLoader.loadClass()传入类路径获取:
ClassLoader.getSystemClassLoader().loadClass("com.hf.lfhferp.entity.TargetObject");
通过类加载器获取的Class对象不会进行初始化,意味着不进行包括初始化等一系列操作,静态代码块和静态对象都不会被执行
反射的一些基本操作
1.创建一个我们要使用的反射操作的类,TargetObject
public class TargetObject {
private String value;
public TargetObject(){
value = "JavaGuide";
}
public void publicMethod(String s){
System.out.println("l love "+s);
}
public void privateMethod(){
System.out.println("value is"+ value);
}
2.使用反射操作这个类的方法以及参数
package com.hf.lfhferp.entity;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String [] args)throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException{
/**
* 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
*/
Class<?> targetClass = Class.forName("com.hf.lfhferp.entity.TargetObject");
TargetObject targetObject = (TargetObject) targetClass.newInstance();
/*获取TargetObject定义的所有方法*/
Method[] methods = targetClass.getDeclaredMethods();
for(Method method :methods){
System.out.println(method.getName());
}
/**
* 获取指定方法并调用
*/
Method publiMethod = targetClass.getDeclaredMethod("publicMethod", String.class);
publiMethod.invoke(targetObject,"Java");
/*获取指定参数并对参数进行修改*/
Field field = targetClass.getDeclaredField("value");
/*为了对类中的参数进行修改我们取消了安全检查*/
field.setAccessible(true);
field.set(targetObject,"Java");
/*调用private方法*/
Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
//为了调用private方法我们取消了安全检查
privateMethod.setAccessible(true);
privateMethod.invoke(targetObject);
}
}
大佬