java参数名称_获取方法参数名称

本文介绍了如何通过Javassist库读取Java类文件中的局部变量表信息,包括静态方法、实例方法以及重名方法的参数名称。Javassist是一个开源的字节码操作工具,虽然性能略低于ASM,但具有更好的可读性。通过设置javac编译器的-g选项可以确保class文件包含局部变量表。示例代码展示了如何获取指定方法的参数名称,以及处理找不到局部变量表信息的情况。
摘要由CSDN通过智能技术生成

a12980d525dff01882bcd17e0dbf8333.png

再看一下包含局部变量表的class文件结构:

fe613fa8ae63983159f09aba2cb0dae8.png

要控制是否生成局部变量表,用javac –g参数选项:

20dff676e4887a52b2e08103229c68bd.png

在Eclipse中这样设置:

6ea04d32e283aae2670a4d7e5477fdb0.png

接下来借助于一款字节码工具来读取局部变量表信息。Javassist是东京工业大学Shigeru Chiba编写的开源的字节码工具包,相对于ASM,性能稍低,但可读性更好,如果用Struts2的话,它已经被包含在xwork-core.jar文件中,所以不需要额外导入了。

package my;

import java.util.Arrays;

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

import javassist.Modifier;

import javassist.NotFoundException;

import javassist.bytecode.CodeAttribute;

import javassist.bytecode.LocalVariableAttribute;

import javassist.bytecode.MethodInfo;

@SuppressWarnings("unchecked")

public class Hello {

public static void main(String[] args) throws Exception {

// 匹配静态方法

String[] paramNames = getMethodParamNames(Hello.class, "main", String[].class);

System.out.println(Arrays.toString(paramNames));

// 匹配实例方法

paramNames = getMethodParamNames(Hello.class, "foo", String.class);

System.out.println(Arrays.toString(paramNames));

// 自由匹配任一个重名方法

paramNames = getMethodParamNames(Hello.class, "getMethodParamNames");

System.out.println(Arrays.toString(paramNames));

// 匹配特定签名的方法

paramNames = getMethodParamNames(Hello.class, "getMethodParamNames", Class.class, String.class);

System.out.println(Arrays.toString(paramNames));

}

/**

* 获取方法参数名称,按给定的参数类型匹配方法

*

* @param clazz

* @param method

* @param paramTypes

* @return

* @throws NotFoundException

* 如果类或者方法不存在

* @throws MissingLVException

* 如果最终编译的class文件不包含局部变量表信息

*/

public static String[] getMethodParamNames(Class clazz, String method, Class... paramTypes)

throws NotFoundException, MissingLVException {

ClassPool pool = ClassPool.getDefault();

CtClass cc = pool.get(clazz.getName());

String[] paramTypeNames = new String[paramTypes.length];

for (int i = 0; i < paramTypes.length; i++)

paramTypeNames[i] = paramTypes[i].getName();

CtMethod cm = cc.getDeclaredMethod(method, pool.get(paramTypeNames));

return getMethodParamNames(cm);

}

/**

* 获取方法参数名称,匹配同名的某一个方法

*

* @param clazz

* @param method

* @return

* @throws NotFoundException

* 如果类或者方法不存在

* @throws MissingLVException

* 如果最终编译的class文件不包含局部变量表信息

*/

public static String[] getMethodParamNames(Class clazz, String method) throws NotFoundException, MissingLVException {

ClassPool pool = ClassPool.getDefault();

CtClass cc = pool.get(clazz.getName());

CtMethod cm = cc.getDeclaredMethod(method);

return getMethodParamNames(cm);

}

/**

* 获取方法参数名称

*

* @param cm

* @return

* @throws NotFoundException

* @throws MissingLVException

* 如果最终编译的class文件不包含局部变量表信息

*/

protected static String[] getMethodParamNames(CtMethod cm) throws NotFoundException, MissingLVException {

CtClass cc = cm.getDeclaringClass();

MethodInfo methodInfo = cm.getMethodInfo();

CodeAttribute codeAttribute = methodInfo.getCodeAttribute();

LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);

if (attr == null)

throw new MissingLVException(cc.getName());

String[] paramNames = new String[cm.getParameterTypes().length];

int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;

for (int i = 0; i < paramNames.length; i++)

paramNames[i] = attr.variableName(i + pos);

return paramNames;

}

/**

* 在class中未找到局部变量表信息

* 使用编译器选项 javac -g:{vars}来编译源文件

*

* @author Administrator

*

*/

public static class MissingLVException extends Exception {

static String msg = "class:%s 不包含局部变量表信息,请使用编译器选项 javac -g:{vars}来编译源文件。";

public MissingLVException(String clazzName) {

super(String.format(msg, clazzName));

}

}

static void foo() {

}

void foo(String bar) {

}

}

运行结果如下:

[args]

[bar]

[clazz, method, paramTypes]

[clazz, method]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值