• 使用ASM获得JAVA类方法参数名


    在Java1.8之后,可以通过反射API java.lang.reflect.Executable.getParameters来获取到方法参数的元信息,
    (在使用编译器时加上-parameters参数,它会在生成的.class文件中额外存储参数的元信息)
    但是在JDK1.7及以下版本的API并不能获取到函数的参数名称,这时候可以使用字节码工具ASM来实现这一功能.

    package yyl.example.demo.asm;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.Arrays;
    
    import org.objectweb.asm.ClassAdapter;
    import org.objectweb.asm.ClassReader;
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.Label;
    import org.objectweb.asm.MethodAdapter;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Type;
    
    /**
     * 使用ASM获得JAVA类方法参数名
     */
    public class GetMethodParamNameTest {
    
        static class Test {
            void method(String name, Object value) {
            }
        }
    
        public static void main(String[] args) throws SecurityException, NoSuchMethodException, IOException {
            Method method1 = Test.class.getDeclaredMethod("method", String.class, Object.class);
           System.out.println(Arrays.toString(getMethodParamNames(method)));
        }
    /** 使用字节码工具ASM来获取方法的参数名 */
        public static String[] getMethodParamNames(final Method method) throws IOException {
    
            final String methodName = method.getName();
            final Class<?>[] methodParameterTypes = method.getParameterTypes();
            final int methodParameterCount = methodParameterTypes.length;
            final String className = method.getDeclaringClass().getName();
            final boolean isStatic = Modifier.isStatic(method.getModifiers());
            final String[] methodParametersNames = new String[methodParameterCount];
    
            ClassReader cr = new ClassReader(className);
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            cr.accept(new ClassAdapter(cw) {
                public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    
                    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    
                    final Type[] argTypes = Type.getArgumentTypes(desc);
    
                    //参数类型不一致
                    if (!methodName.equals(name) || !matchTypes(argTypes, methodParameterTypes)) {
                        return mv;
                    }
                    return new MethodAdapter(mv) {
                        public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                            //如果是静态方法,第一个参数就是方法参数,非静态方法,则第一个参数是 this ,然后才是方法的参数
                            int methodParameterIndex = isStatic ? index : index - 1;
                            if (0 <= methodParameterIndex && methodParameterIndex < methodParameterCount) {
                                methodParametersNames[methodParameterIndex] = name;
                            }
                            super.visitLocalVariable(name, desc, signature, start, end, index);
                        }
                    };
                }
            }, 0);
            return methodParametersNames;
        }
    
        /**
         * 比较参数是否一致
         */
        private static boolean matchTypes(Type[] types, Class<?>[] parameterTypes) {
            if (types.length != parameterTypes.length) {
                return false;
            }
            for (int i = 0; i < types.length; i++) {
                if (!Type.getType(parameterTypes[i]).equals(types[i])) {
                    return false;
                }
            }
            return true;
        }
    
    }

    备注:JDK 自带类 ,接口方法和抽象方法无法使用这种方式获取参数名

  • 相关阅读:
    质数检测器
    《视觉SLAM十四讲》学习日志(一)——预备知识
    C++类的介绍
    Python数据类型解析(基础篇)
    括号匹配详解
    哈夫曼树编码
    分治之归并,快速排序
    洛谷p2216 多次单调队列,扫描矩阵中的最大值减去最小值最的固定大小子矩阵
    洛谷p1886滑动窗口最大最小值 双单调队列
    洛谷p1725 露琪诺 单调队列优化的DP
  • 原文地址:https://www.cnblogs.com/relucent/p/6525821.html
Copyright © 2020-2023  润新知