zl程序教程

您现在的位置是:首页 >  后端

当前栏目

获取Java方法参数的名称

JAVA方法 获取 参数 名称
2023-09-14 09:03:16 时间

最近有个需求,需要获取java方法参数的名称,网上查了下,然后自己也实践了下,总结出3点:
1.能不能获取方法参数的名称取决于class文件里是否含有LocalVariableTable。
2.javac编译生成的class文件不含有LocalVariableTable,但是eclipse编译生成的class文件却含有LocalVariableTable。
3.有2种方式可以获得,用Asm和Javassist,Asm的性能略高。
贴代码:

maven依赖:

 dependency 

 groupId org.javassist /groupId 

 artifactId javassist /artifactId 

 version 3.18.0-GA /version 

 /dependency 

 dependency 

 groupId org.ow2.asm /groupId 

 artifactId asm /artifactId 

 version 4.1 /version 

 /dependency 

User类:

/**

 * @author a href="mailto:yankai913@gmail.com" yankai /a 

 * @date 2013-7-17

public class User {

 String name;

 String address;

 int age;

 public User(String name, String address, int age) {

 this.name = name;

 this.address = address;

 this.age = age;

 public static User newInstance(String name, String address, int age) {

 return new User(name, address, age);

 public User copy(String name, String address, int age) {

 return new User(name, address, age);

asm实现:

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

import org.objectweb.asm.ClassReader;

import org.objectweb.asm.ClassVisitor;

import org.objectweb.asm.Label;

import org.objectweb.asm.MethodVisitor;

import org.objectweb.asm.Opcodes;

 * @author a href="mailto:yankai913@gmail.com" yankai /a 

 * @date 2013-7-17

public class AsmTool {

 private static boolean sameType(Type[] types, Class ? [] clazzes) {

 if (types.length != clazzes.length) {

 return false;

 for (int i = 0; i types.length; i++) {

 if (!Type.getType(clazzes[i]).equals(types[i])) {

 return false;

 return true;

 public static String[] getMethodParamNames(final Method m) throws Exception {

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

 String methodClass = m.getDeclaringClass().getName();

 ClassReader cr = new ClassReader(methodClass);

 cr.accept(new ClassVisitor(Opcodes.ASM4) {

 @Override

 public MethodVisitor visitMethod(final int access,

 final String name, final String desc,

 final String signature, final String[] exceptions) {

 Type[] args = Type.getArgumentTypes(desc);

 if (!name.equals(m.getName())

 || !sameType(args, m.getParameterTypes())) {

 return null;

 return new MethodVisitor(Opcodes.ASM4) {

 @Override

 public void visitLocalVariable(String name, String desc,

 String signature, Label start, Label end, int index) {

 int i = index - 1;

 if (Modifier.isStatic(m.getModifiers())) {

 i = index;

 if (i = 0 i paramNames.length) {

 paramNames[i] = name;

 }, 0);

 return paramNames;

asm测试:

import java.lang.reflect.Method;

import java.util.Arrays;

 * @author a href="mailto:yankai913@gmail.com" yankai /a 

 * @date 2013-7-17

public class TestAsm {

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

 long start = System.currentTimeMillis();

 final Method method = 

 User.class.getMethod("newInstance", new Class ? []{String.class, String.class, int.class});

 String[] s = AsmTool.getMethodParamNames(method);

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

 System.out.println(System.currentTimeMillis() - start);//40

javassist实现:

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

import javassist.Modifier;

import javassist.bytecode.CodeAttribute;

import javassist.bytecode.LocalVariableAttribute;

import javassist.bytecode.MethodInfo;

 * @author a href="mailto:yankai913@gmail.com" yankai /a 

 * @date 2013-7-17

public class JavassistTool {

 // ClassLoader, ClassPool 

 static final Map ClassLoader, ClassPool pool2map = 

 new ConcurrentHashMap ClassLoader, ClassPool 

 public static String[] getMethodParamNames(Method method)

 throws Exception {

 Class ? clazz = method.getDeclaringClass();

 String methodName = method.getName();

 ClassPool pool = ClassPool.getDefault();

 CtClass cc = null;

 try {

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

 } catch (Exception e) {

 if (e instanceof NotFoundException) {

 pool = pool2map.get(clazz.getClassLoader());

 if (pool == null) {

 pool = new ClassPool(true);

 pool.appendClassPath(new LoaderClassPath(clazz.getClassLoader()));

 pool2map.put(clazz.getClassLoader(), pool);

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

 CtMethod cm = cc.getDeclaredMethod(methodName);

 MethodInfo methodInfo = cm.getMethodInfo();

 CodeAttribute codeAttribute = methodInfo.getCodeAttribute();

 LocalVariableAttribute attr = 

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

 if (attr == null) {

 throw new IllegalStateException("LocalVariableAttribute is null");

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

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

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

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

 return paramNames;

javassist测试:

import java.util.Arrays;

 * @author a href="mailto:yankai913@gmail.com" yankai /a 

 * @date 2013-7-17

public class TestJavassist {

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

 long start = System.currentTimeMillis();

 String[] paramNames = JavassistTool.getMethodParamNames(User.class, "newInstance");

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

 System.out.println(System.currentTimeMillis() - start);//90


Java String 的 常量池 和 intern 方法 简析 Java String 的 常量池 和 intern 方法 简析字符串常量池和 intern 方法 先举个例子,我们创建 10000 个相同的 String,并且不使用常量池 String[] list = new String[10000]; for (int i = 0; i 10000; i++) { list[i] = new String(new char[]{ a , b , c 结果是:每个 String 都用新开的对象,占用大量内存
现在我们这样创建,增加一个 map ,key 和 value 内容一样,每次取的时候,先检查一下 map 里面有没
Java的学习笔记(04)方法 Java方法01 方法是语句的集合,执行一个功能。方法再程序中被创建,再其他地方被引用 一个方法只做一个功能 方法的命名规则:首字母小写,驼峰规则。 package method; public class Demo01 { //mian 方法 public static void main(String[] args) { int sum = add(1,2); //调用一个方法:加法 // 实际参数:实际调用传递给
【Java编程进阶】方法初识 方法是组合在一起来执行操作语句的集合`,将具有独立功能的代码块组织成为一个整体,使其具有特殊功能,并且能实现达到代码复用的效果。例如我们要在程序中多次判断一个数字是奇数还是偶数,这时,我们就可以将判断一个数的奇偶性的代码段封装成一个方法,后面再使用时只需要调用这个方法,大大提高了编程的效率和代码的复用性。
Java练习题——抽象类、方法以及接口 由于三种动物都有共同属性:名字和属性,并且有共同行为:吃,所以只需要在共同父类(Animal)中编写标准Javabean类即可
Java练习题——方法(基础版) 求数组内最大值以及定义一个随机数组在之前已经介绍过了,只需要将这部分的代码打包放在一个方法内,并在main方法中调用即可