怎样提高反射的效率?
java
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } return method; } private Method getMethod0(String name, Class<?>[] parameterTypes) { if ((res = searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) != null) { return res; } if (!isInterface()) { Class<? super T> c = getSuperclass(); if (c != null) { if ((res = c.getMethod0(name, parameterTypes)) != null) { return res; } } } Class<?>[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { Class<?> c = interfaces[i]; if ((res = c.getMethod0(name, parameterTypes)) != null) { return res; } } return null; } private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { Method res = null; String internedName = name.intern(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (m.getName() == internedName && arrayContentsEq(parameterTypes, m.getParameterTypes()) && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } return (res == null ? res : getReflectionFactory().copyMethod(res)); }
顺便看一下getMethod方法,如果类的方法不是很多,getMethod和getMethods方法差距不是很大。差距在于自己写轮寻和系统自带轮寻之间的效率。
说了半天,都没有人提到"setAccessible(true)"...楼上的各位不是资深java程序员吧?
edit:
实话地告诉你,JDK1.6之后,对于method/field/constructor的invoke这类的反射,除了"setAccessible(true)"之外,再无须其它任何优化, 完爆以前cglib的fastmethod之流
当然了,将得到的method/field/constructor对象做缓存这是基本的
07-31 edit:
忘了补充一句:
如果你在jdk6上跑,且如果你反射的目标方法是getter/setter methods的话,记得加上配置:-XX:-UseFastEmptyMethods -XX:-UseFastAccessorMethods , 这两个配置的关闭是为了让accessor methods能够被jit; jdk7以上不需要设置这两个配置
要使用类信息,少查找class, field, method,缓存很重要,还有办法是生成代理类。要复制对象可以用CGLib的BeanCopier (其原理是运行时动态生成了用于复制某个类的代码(字节码))。
要提高Method.invoke性能,可用Java 7的MethodHandle (由于Method.invoke的JIT优化,差距不大)。
使用高版本JDK也很重要,反射性能一直在提高。
12 回答5.8k 阅读
2 回答3.2k 阅读✓ 已解决
3 回答6.9k 阅读✓ 已解决
3 回答3k 阅读✓ 已解决
5 回答4.6k 阅读
4 回答2.3k 阅读
3 回答4.4k 阅读
一. 善用API
比如,尽量不要
getMethods()
后再遍历筛选,而直接用getMethod(methodName)
来根据方法名获取方法二、缓存大法好~
比如,需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多:
为什么?当然是因为forName太耗时了。
p.s. cache请自行实现