在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 自帶類 ,接口方法和抽象方法無法使用這種方式獲取參數名