在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 自带类 ,接口方法和抽象方法无法使用这种方式获取参数名

使用ASM获得JAVA类方法参数名的更多相关文章

  1. java使用省略号代替多参数(参数类型... 参数名)

    J2SE 1.5提供了“Varargs”机制.借助这一机制,可以定义能和多个实参相匹配的形参.从而,可以用一种更简单的方式,来传递个数可变的实参.本文介绍这一机制的使用方法,以及这一机制与数组.泛型. ...

  2. 【转】使用JavaParser获得Java代码中的类名、方法形参列表中的参数名以及统计总的文件个数与不能解析的文件个数

    遍历目录查找Java文件: public static void ergodicDir(File dir, HashSet<String> argNameSet, HashSet<S ...

  3. Java获取方法参数名、Spring SpEL解析

    @Test public void testParse() { //表达式解析 ExpressionParser expressionParser = new SpelExpressionParser ...

  4. Spring LocalVariableTableParameterNameDiscoverer获取方法的参数名

    Spring LocalVariableTableParameterNameDiscoverer获取方法的参数名 问题:Java.lang.reflect 包中提供了很多方法,获取所有的方法,获取所有 ...

  5. 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】

    每篇一句 胡适:多谈些问题,少聊些主义 前言 Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用.如果你往深了一步去思考,你应该会有这样的疑问: 在使用Spring ...

  6. Java 类方法和类变量

    目录 一.类变量 1.如果定义类变量 2.如何访问类变量 3.类变量的使用注意事项和细节 二.类方法 1.类方法的形式 2.类方法的调用 3.类方法经典使用场景 4.类变量和类方法 三.main方法 ...

  7. request.getParameter(“参数名”) 中文乱码解决方法

    今天浏览项目时候,遇到一个问题,页面用${requestScope.参数名 }获取的值是乱码,然后搜了一下,最后说是编码的问题,附上查找的结果: 在Java 开发中,如果框架搭建的不完善或者初学者在学 ...

  8. Java学习-025-类名或方法名应用之一 -- 调试源码

    上文讲述了如何获取类名和方法名,敬请参阅: Java学习-024-获取当前类名或方法名二三文 . 通常在应用开发中,调试或查看是哪个文件中的方法调用了当前文件的此方法,因而在实际的应用中需要获取相应的 ...

  9. Java可变参数 & Python可变参数 & Scala可变参数

    Java 可变参数的特点: (1).只能出现在参数列表的最后: (2)....位于变量类型和变量名之间,前后有无空格都可以: (3).调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体 ...

随机推荐

  1. eclipse package explorer视图中怎么让default package不显示?

    如下图所示:

  2. Solr6.6 IK 中文分词的配置和使用

    1. 首先,下载IKAnalyzer ,下载 2. 将ik的相关文件 拷贝到 webapps\solr\WEB-INF\lib 目录下 或者存放solr-6.6.0\server\solr\test\ ...

  3. Hive计算的临时文件清理

    hive 的存储路径的 .hive-staging_hive_yyyy-MM-dd_HH-mm-ss_SSS_xxxx-x 文件可以清理掉吗 https://blog.csdn.net/sparkex ...

  4. DevExpress TreeList使用

    using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; us ...

  5. DevExpress TreeList使用教程之绑定多级树

    DevExpress TreeList使用教程之绑定多级树   概述:TreeList控件可以同时显示树结构和其他数据列,即在一个列上建立父子关系展开或收缩,同时还可以显示其他列的内容.在TreeLi ...

  6. 用开源NGINX-RTMP-MODULE搭建FLASH直播环境

    用开源nginx-rtmp-module搭建flash直播环境 1.将nginx和nginx-rtmp-module的源码包解压PS:nginx-rtmp-module网址https://github ...

  7. UVa145 Gondwanaland Telecom

    Time limit: 3.000 seconds 限时:3.000秒 Problem 问题 Gondwanaland Telecom makes charges for calls accordin ...

  8. Loadrunner关于页面检查的几个函数详解

    环境:Loadrunner版本:8.0自建一个test.html文件:<html><head><meta name="google1" content ...

  9. 模块化开发RequireJS之shim配置

    一.shim requirejs使用AMD规范开发,若开发过程中加载非AMD规范js,需要使用requirejs的shim进行配置. shim配置语法为: //配置文件 requirejs.confi ...

  10. Android Exception 9(requestFeature() must be called before adding content)

    08-05 17:36:12.799: W/System.err(10378): java.lang.reflect.InvocationTargetException08-05 17:36:12.7 ...