使用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 自带类 ,接口方法和抽象方法无法使用这种方式获取参数名
使用ASM获得JAVA类方法参数名的更多相关文章
- java使用省略号代替多参数(参数类型... 参数名)
J2SE 1.5提供了“Varargs”机制.借助这一机制,可以定义能和多个实参相匹配的形参.从而,可以用一种更简单的方式,来传递个数可变的实参.本文介绍这一机制的使用方法,以及这一机制与数组.泛型. ...
- 【转】使用JavaParser获得Java代码中的类名、方法形参列表中的参数名以及统计总的文件个数与不能解析的文件个数
遍历目录查找Java文件: public static void ergodicDir(File dir, HashSet<String> argNameSet, HashSet<S ...
- Java获取方法参数名、Spring SpEL解析
@Test public void testParse() { //表达式解析 ExpressionParser expressionParser = new SpelExpressionParser ...
- Spring LocalVariableTableParameterNameDiscoverer获取方法的参数名
Spring LocalVariableTableParameterNameDiscoverer获取方法的参数名 问题:Java.lang.reflect 包中提供了很多方法,获取所有的方法,获取所有 ...
- 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】
每篇一句 胡适:多谈些问题,少聊些主义 前言 Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用.如果你往深了一步去思考,你应该会有这样的疑问: 在使用Spring ...
- Java 类方法和类变量
目录 一.类变量 1.如果定义类变量 2.如何访问类变量 3.类变量的使用注意事项和细节 二.类方法 1.类方法的形式 2.类方法的调用 3.类方法经典使用场景 4.类变量和类方法 三.main方法 ...
- request.getParameter(“参数名”) 中文乱码解决方法
今天浏览项目时候,遇到一个问题,页面用${requestScope.参数名 }获取的值是乱码,然后搜了一下,最后说是编码的问题,附上查找的结果: 在Java 开发中,如果框架搭建的不完善或者初学者在学 ...
- Java学习-025-类名或方法名应用之一 -- 调试源码
上文讲述了如何获取类名和方法名,敬请参阅: Java学习-024-获取当前类名或方法名二三文 . 通常在应用开发中,调试或查看是哪个文件中的方法调用了当前文件的此方法,因而在实际的应用中需要获取相应的 ...
- Java可变参数 & Python可变参数 & Scala可变参数
Java 可变参数的特点: (1).只能出现在参数列表的最后: (2)....位于变量类型和变量名之间,前后有无空格都可以: (3).调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体 ...
随机推荐
- unity 显示mipmaplevel
https://docs.unity3d.com/ScriptReference/Texture2D.SetPixels.html 显示mipmaplevel 需要贴图可读写不压缩 using Uni ...
- es服务
#!/bin/bash #chkconfig:2345 20 90 #description: elastic service #processname: elastic ROOT_PATH=/es5 ...
- Springboot配置文件加载顺序
使用Springboot开发的时候遇到了配置的问题,外部config里的配置文件本来没有配置https怎么启动还是https呢,原来开发中测试https在classpath路径的配置文件添加https ...
- Django 学习记录
这是我自己理解并自己画的,django 请求示意图,表示了它的组织方式. project manage.py: 主要工具文件 settings.py: 配置文件 urls.py: url 定义及其指向 ...
- Ubuntu 下安装adobe reader
ctrl+alt+t打开终端 wget ftp://ftp.adobe.com/pub/adobe/reader/unix/9.x/9.5.5/enu/AdbeRdr9.5.5-1_i386linux ...
- c# 句柄数不断攀升的解决方案
句柄只是用来标识应用程序中的不同对象和同类中的不同的实例的一个数字,通常情况下,句柄值对普通用户毫无用处,但是句柄数量却可以间接反映出一个程序里产生的对象实例的多少.句柄数越多,代表程序里new 出来 ...
- 初识 Swift编程语言(中文版)
前言 今天Apple公布了新的编程语言Swift.也提供了一本将近400页的 The Swift Programming Language(Swift编程语言). 尽管我没有开发人员账号.没法实际上机 ...
- Loadrunner关于页面检查的几个函数详解
环境:Loadrunner版本:8.0自建一个test.html文件:<html><head><meta name="google1" content ...
- 获取ping的最短、最长、平均时间
# -*- coding: utf-8 -*- import osimport rep = os.popen('ping 120.26.77.101') out = p.read()regex = r ...
- 微信小程序navigateBack如何带参数
wx.navigateBack({//返回 delta:1 }) 方法如下: 一. var pages = getCurrentPages(); var prevPage = pages[page ...