反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。
通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
Java 反射主要提供以下功能:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
- 在运行时调用任意一个对象的方法
很多人都认为反射在实际的 Java 开发应用中并不广泛,其实不然。当我们在使用 IDE(如 Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点号,编译器就会自动列出它的属性或方法,这里就会用到反射。
反射最重要的用途就是开发各种通用框架。很多框架(比如 Spring)都是配置化的(比如通过 XML 文件配置 Bean),为了保证框架的通用性,它们可能需要根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射,运行时动态加载需要加载的对象。
反射的基本运用
- 获取class 对象。
- 获取Months方法。
调用invoke
方法。
封装反射工具对象
public class ReflectApplyUtils {
/**
* 根据类名称和方法名称执行指定类的指定方法
* 获取public方法
* Method[] method01 = clasz.getMethods();
* 获取private方法
* Method[] method02 = clasz.getDeclaredMethods();
*/
public static Object executeByName(String className, String methodName, Object params) {
Object result = null;
try {
//1.根据类名称获取该类对应的Class对象
Class<?> clasz = Class.forName(className);
//2.根据方法名称获取改方法对应的Method对象
Method method = null;
for (Method var1 : clasz.getMethods()) {
if (StringUtils.equals(var1.getName(), methodName)) {
method = var1;
break;
}
}
//3.执行具体方法
if (method != null) {
//获取方法的Modifier值,在根据Modifier定义的常量可以判断方式是哪种类型
int var2 = method.getModifiers();
if (Modifier.isPublic(var2) && Modifier.isStatic(var2)) {
result = method.invoke(clasz, params);
} else if (Modifier.isPublic(var2) && !Modifier.isStatic(var2)) {
result = method.invoke(clasz.newInstance(), params);
} else {
throw new Exception("提供的方法名称: " + methodName + ",不是public类型,无权限执行.");
}
} else {
throw new Exception("根据方法名称: " + methodName + ",无法找到对应Method,请检查输入的方法名称是否正确.");
}
} catch (Exception e) {
result = e;
}
return result;
}
}
使用案例
/**
* 执行MainBizRealDataPushService中的test()方法并获取到结果。
**/
Object executeResult = ReflectApplyUtils.executeByName("com.talent.work.biz.service.dataanalysis.MainBizRealDataPushService", "test", (byte)0);
反射的一些注意事项
- 由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。
- 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。