在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. Centos&RHEL 6安装图形化

    Linux是一个多任务的多用户的操作系统,而在安装linux的时候经常遇到的问题-没有图形化桌面.在上节中我们演示了RHEL7安装图形化的过程,下面我们演示Centos6的图形化安装. 一.Cento ...

  2. 利用HTML5与jQuery技术创建一个简单的自动表单完成

    来源:GBin1.com 在线演示   在线下载 谷歌快速搜索自带大量自动完成插件——库中甚至还有一个附带的jQuery UI共享选项.然而今天我要寻找一个替代的解决方案.由DevBridge开发的j ...

  3. Java调用本地接口:java.lang.UnsatisfiedLinkError

    Java调用本地接口:java.lang.UnsatisfiedLinkError 我的问题不在这篇文章描述中, 而是因为jni原来是c实现, 现在切换到cpp了, 需要在对应的cpp文件中加入ext ...

  4. Git库搭建好之后,当要提交一个新的文件,需要做的是3个步骤

    Git库搭建好之后,当要提交一个新的文件,需要做的是3个步骤 1.git add new.txt 2.git commit -m "add a new file" 3.git pu ...

  5. vc 获取函数名称真实地址

    首先写一个很简单的main函数: int main(){ printf("main的地址(?):%08x",main); } 单步调试,可得知 main函数的真实入口地址是:00b ...

  6. Hibernate关系映射(一) 基于外键的单向一对一

    模拟用户和地址的映射关系,一个用户只有一个地址,用户知道地址,但是地址不知道用户.用户对地址的单向一对一映射. 一.建立实体类 Account.cs类 package com.lxit.entity; ...

  7. 禁止chrome自动更新

    删除C:\Program Files (x86)\Google文件夹下面的updata文件夹

  8. Oracle查询及删除重复数据

    1.查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断 ) 2.删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录 ) ); 3.查找表中多余的重复记录 ...

  9. Android给TextView设置透明背景、圆角边框

    第一种方法:在drawable文件夹下新建一个文件设置背景样式 代码: 在drawable文件夹下面新建text_view_border.xml <?xml version="1.0& ...

  10. [转]PHP运行出现Notice : Use of undefined constant 的完美解决方案

    Notice: Use of undefined constant title - assumed 'title' in F:\wamp\www\load_myweb.php on line 22No ...