首先来了解一下 Java中为什么需要反射?反射要解决什么问题?
一句话概括就是使用反射可以赋予jvm动态编译的能力,否则类的元数据信息只能用静态编译的方式实现,例如热加载,Tomcat的classloader等等都没法支持
Java中编译类型有两种:
静态编译:在编译时确定类型,绑定对象即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性。
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public、static等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
Reflection可以在运行时加载、探知、使用编译期间完全未知的classes。即Java程序可以加载一个运行时才得知名称的class,获取其完整构造,并生成其对象实体、或对其fields设值、或唤起其methods。
反射(reflection)允许静态语言在运行时(runtime)检查、修改程序的结构与行为。
在静态语言中,使用一个变量时,必须知道它的类型。在Java中,变量的类型信息在编译时都保存到了class文件中,这样在运行时才能保证准确无误;换句话说,程序在运行时的行为都是固定的。如果想在运行时改变,就需要反射这东西了。
实现Java反射机制的类都位于java.lang.reflect包中:
1、Class类:代表一个类
2、Field类:代表类的成员变量(类的属性)
3、Method类:代表类的方法
4、Constructor类:代表类的构造方法
5、Array类:提供了动态创建数组,以及访问数组的元素的静态方法
* 对于修改静态常量类型是需要小心
对于基本类型的静态常量,JAVA在编译的时候就会把代码中对此常量中引用的地方替换成相应常量值
下面是反射优化过的代码,为什么要优化呢,方法是多次访问的,并不是访问一次就不用了,所以在访问后将它存储起来,避免下次使用还要去查找,浪费性能、时间import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* @author: BUG汇总
* @description: java反射优化类,通过此类可快速获取到对应类的方法
* @className: DynamicServer
* @createDate: 2020-06-02 09:21:40
*/
public class DynamicServer {
private static Logger logger = Logger.getLogger(DynamicServer.class);
private static Map clazzMap = new HashMap();
private static Map objMap = new HashMap();
private static Map metMap = new HashMap();
private static Map> typeMap = new HashMap>();
/**
* @author: BUG汇总
* @description: 通过反射+缓存高效的调用某个类里面的某个方法
* @createDate: 2020-06-02 09:22:20
* @param clazz 类名
* @param method 方法名
* @param os 方法参数 例如 ["参数"]
* @param cs 参数的类型 例如 [String.class] OS和 CS位置对应
* @return java.lang.Object
*/
public static Object cacheExce(String clazz,String method,Object[] os,Class[] cs) throws Exception{
int size = 0;
if(cs!=null){
size = cs.length;
}
Method m = metMap.get(clazz+"_"+method+"_"+size);//用于区分重载的方法
Object obj = objMap.get(clazz);
if(m==null||obj==null){
Class cl = clazzMap.get(clazz);
if(cl==null){
cl = Class.forName(clazz);
clazzMap.put(clazz, cl);//缓存class对象
}
if(obj==null){
obj = cl.newInstance();
objMap.put(clazz, obj);//缓存对象的实例
}
if(m==null){
m = cl.getMethod(method, cs);
metMap.put(clazz+"_"+method+"_"+size, m);//缓存Method对象
}
}
return m.invoke(obj , os);//动态调用某个对象中的public声明的方法
}
/**
* @author: BUG汇总
* @description: 通过反射+缓存获取指定类里面 的指定方法的返回类型
* @createDate: 2020-06-02 09:49:17
* @param clazz
* @param method
* @return java.lang.String
*/
public static String cacheType(String clazz,String method) throws ClassNotFoundException{
Map clazzs = typeMap.get(clazz);
if(clazzs==null){
Map mmap = new HashMap();
Class cl = Class.forName(clazz);
Method[] ms = cl.getMethods();//获取某个类里面的所有的公共的方法
for(Method m:ms){
mmap.put(m.getName(), m.getGenericReturnType().toString());//遍历出所有的方法,将方法名和返回类型存在静态的map中(缓存)
}
clazzs = mmap;
typeMap.put(clazz, mmap);
}
return clazzs.get(method);
}