前提条件

在java8中要获取类函数参数名称必须在编译时增加参数

编译器时加上-parameters参数

具体内容详见 java1.8获取类和接口函数参数名称

尝试使用javassist获取接口函数名称

1 添加依赖

  <dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.23.1-GA</version></dependency>

2 在编译时增加-parameters参数

3 编写测试接口和测试方法

package js.oop.parameter;import javassist.*;
import javassist.bytecode.*;/**
* @Title: IParameterNameJavassist
* @Description: 演示 Javassist 获取接口的函数参数名称
* @author chy
* @date 2018/8/16 16:44
*/
public interface IParameterNameJavassist {public abstract void test1(String myMsg);public abstract void test2(String myMsg,int myAge);public abstract void test3(String myMsg,int myAge, String mySex);/*** 获取类方法参数名称* @param funName*/public static void getClassParamterName(String funName){Class<?> clazz = ParameterNameJavassist.class;ClassPool pool = ClassPool.getDefault();try {CtClass ctClass = pool.get(clazz.getName());CtMethod ctMethod = ctClass.getDeclaredMethod(funName);// 使用javassist的反射方法的参数名MethodInfo methodInfo = ctMethod.getMethodInfo();CodeAttribute codeAttribute = methodInfo.getCodeAttribute();LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);if (attr != null) {int len = ctMethod.getParameterTypes().length;// 非静态的成员函数的第一个参数是thisint pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;System.out.print(funName+" : ");for (int i = 0; i < len; i++) {System.out.print(attr.variableName(i + pos) + ' ');}System.out.println();}System.out.println(funName+"获取结束");} catch (NotFoundException e) {e.printStackTrace();}}/*** 获取接口方法参数名称* @param clazz* @param funName*/public static void getInterfaceParamterName(Class<?> clazz,String funName){ClassPool pool = ClassPool.getDefault();try {CtClass ctClass = pool.get(clazz.getName());CtMethod ctMethod = ctClass.getDeclaredMethod(funName);// 使用javassist的反射方法的参数名MethodInfo methodInfo = ctMethod.getMethodInfo();MethodParametersAttribute methodParameters= (MethodParametersAttribute)methodInfo.getAttribute("MethodParameters");//获取参数的个数int count =ctMethod.getParameterTypes().length;CtClass[] pCtClass= ctMethod.getParameterTypes();for(int i=0;i<count;i++) {String str = methodParameters.getConstPool().getUtf8Info(ByteArray.readU16bit(methodParameters.get(), i * 4 + 1));System.out.println("参数名称:" + str + ",参数类型" + pCtClass[i].getName());}System.out.println("");System.out.println(funName+"获取结束");System.out.println("");} catch (NotFoundException e) {e.printStackTrace();}}public static void main(String[] args) {try {/*** 抽象函数和接口函数*/getInterfaceParamterName(IParameterNameJavassist.class,"test1");getInterfaceParamterName(IParameterNameJavassist.class,"test2");getInterfaceParamterName(IParameterNameJavassist.class,"test3");} catch (Exception e) {System.out.println("获取抽象类/接口函数参数出错");}}
}

4 如果使用 getClassParamterName  函数只能获取 类里面的函数参数名称

5 如果使用 getInterfaceParamterName 函数能获取 类以及抽象类以及接口的函数名称

6 实现原理编译时增加-parameters参数后,字节码中增加了  MethodParameters 元信息,只要能读取元信息就行

 public abstract void test1(java.lang.String);descriptor: (Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_ABSTRACTMethodParameters:Name                           FlagsmyMsgpublic abstract void test2(java.lang.String, int);descriptor: (Ljava/lang/String;I)Vflags: ACC_PUBLIC, ACC_ABSTRACTMethodParameters:Name                           FlagsmyMsgmyAge public abstract void test3(java.lang.String, int, java.lang.String);descriptor: (Ljava/lang/String;ILjava/lang/String;)Vflags: ACC_PUBLIC, ACC_ABSTRACTMethodParameters:Name                           FlagsmyMsgmyAgemySex

7  javassist 中虽然实现了 MethodParametersAttribute 类,但是没有实现获取参数名称的功能,这点很坑啊!!!!

8 无奈看源码,参考 LineNumberAttribute 实现方式,获取 LineNumberAttribute 属性的值

public class LineNumberAttribute extends AttributeInfo {public static final String tag = "LineNumberTable";............public int tableLength() {return ByteArray.readU16bit(this.info, 0);}............public int lineNumber(int i) {return ByteArray.readU16bit(this.info, i * 4 + 4);}............
}

LineNumber  的存储数据格式如下:

public void fun(java.lang.String, int);descriptor: (Ljava/lang/String;I)Vflags: ACC_PUBLICCode:stack=3, locals=3, args_size=3................................37: returnLineNumberTable:line 16: 0line 17: 37LocalVariableTable:Start  Length  Slot  Name   Signature0      38     0  this   Ljs/oop/parameter/ParameterNameJavassist;0      38     1 name1   Ljava/lang/String;0      38     2  age1   IMethodParameters:Name                           Flagsname1age1

9 照葫芦画瓢

//取而第一个参数
str= methodParameters.getConstPool().getUtf8Info(ByteArray.readU16bit(methodParameters.get(), 0 * 4 + 1));System.out.println(str);//取而第二个参数
str= methodParameters.getConstPool().getUtf8Info(ByteArray.readU16bit(methodParameters.get(), 1 * 4 + 1));System.out.println(str);

methodParameters.get()  就是  MethodParameters 的元信息,但是是字节数组,需要转换成字符串

如果有谁知道为什么是  n*4+1 请告知我? n是参数序号从0开始,我是实验出来的!!!!!

10 运行结果

java1.8中javassist获取接口函数参数名称相关推荐

  1. android c 对象为空,ndk-jni中C/C++接口函数修改函数参数jobject对象成员值(数组)的有关问题...

    ndk-jni中C/C++接口函数修改函数参数jobject对象成员值(数组)的问题 现java中有个类: public class TestClass { private int nValue; p ...

  2. Java获取函数参数名称

    原理 编译之后的class文件默认是不带有参数名称信息的,使用 IDE 时,反编译jar包得到的源代码函数参数名称是 arg0,arg1......这种形式,这是因为编译 jar 包的时候没有把符号表 ...

  3. 有没有更好的方法在JavaScript中执行可选的函数参数? [重复]

    本文翻译自:Is there a better way to do optional function parameters in JavaScript? [duplicate] This quest ...

  4. python中args和kwargs_Python 函数参数*args和**kwargs

    尽管*args和**kwargs参数不受重视,但这它们是Python中非常有用的特性.了解其中的潜能会让你成为更高效的开发者. *args和**kwargs参数到底有什么用呢?它们能让函数接受可选参数 ...

  5. C#调用VC的DLL的接口函数参数类型转换一览表

    handle---------IntPtr hwnd-----------IntPtr char *----------string int * -----------ref int int & ...

  6. 第5.2节 Python中带星号的函数参数实现参数收集

    函数的参数使用除了常规的位置参数和关键字参数外,还支持可变个数的函数参数,这种支持可变个数的参数方法称为参数收集,对应的参数称为收集参数. 一.参数收集的定义 Python的函数支持可变不定数量的参数 ...

  7. C/C++中,数组作为函数参数传入

    函数的参数可以是数组,且数组作为参数传入时,参数中数组的第一维不需要填写长度,如果是二维,那么第二维需要填写长度,在实际调用时也只需填写数组名.最重要的是,数组作为参数时,在函数中对数组元素的修改就等 ...

  8. 替代GDA中的获取rpc函数poDataset->GetMetadata(“RPC“)

    使用gdal获取经纬度可以通过API this->poDataset->GetMetadata("RPC")来自动实现定位rpc文件,并且将内容读入到char** pa ...

  9. shell脚本中如何获取命令的参数(2) ----处理命令参数

    1    找出选项 1.1 处理简单选项 主要可以通过shfit工具对获取的到$1变量对比程序允许的变量值判断: 1.2  从参数中分离选项 一般参数可能在后面跟上适当的参数值,例如 sed   -f ...

最新文章

  1. [置顶] 我的GB28181标准开发里程碑——基于eXosip的IPC端与SPVMN注册成功
  2. python匿名函数调用_python3笔记十六:python匿名函数和高阶函数
  3. java使用MD5加密
  4. 《编码的奥秘》---学习编程一年半的体会
  5. IdentityServer4实战 - 与API单项目整合
  6. Win32+API学习笔记:创建基本的窗口控件
  7. beaninfo详解源码解析 java_Java后端精选技术:源码解析Spring Cloud Zuul
  8. edHat linux光盘引导,[原]个性化Linux发行版光盘之补充——XZ(LZMA算法)
  9. 百度富文本编辑器UEditor
  10. 计算机组成原理mips汇编大作业报告(冒泡排序、选择排序)
  11. linux下批量替换文件内容
  12. 无脑安装教程:windows 10—QT5.9.5 + vs2013
  13. android调用拨号界面拨打电话功能,Android实现拨打电话功能
  14. 11个经典物联网应用电路方案优选合辑
  15. Oracle学习—图书管理系统_存储过程
  16. 对谈 | 创新与进化——当开源接受SaaS
  17. 山财计算机考试科目,山东财经大学考研——22考研儿注意了,这几所高校发布了初试科目变更通知...
  18. 中标麒麟桌面操作系统7.0安装QT5.9.9完整教程(附安装包)
  19. 淘宝网上新手卖家的40条开店准备笔记
  20. 书虫英文读后感——猴爪(The Monkey's Paw)

热门文章

  1. Python图像处理笔记——傅里叶变换
  2. Python图像处理基本操作
  3. 关于环境变量/etc/environment
  4. 【故障诊断】用于轴承故障诊断的性能增强时变形态滤波方法及用于轴承断层特征提取的增强数学形态算子研究(Matlab代码实现)
  5. 小说分享《Mehul和我》前三分之二段
  6. 成都公积金提取流程(自住住房贷款)
  7. 怎么彻底卸载cad2017_mac装了2017cad后卸载后,想把该软件注册表里的东西也删除,不知道如何处理?...
  8. javascript集合的使用 new Set()使用
  9. 如何更换jupyter notebook的默认浏览器
  10. checkedlistbox添加object的方式