获取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方法中调用即可
相关文章
- java线程池的面试题_献给准备面试的你,Java线程and线程池面试题小结「建议收藏」
- 反应java程序并行机制的特点_Java语言具有许多优点和特点,下列选项中能反映Java程序并行机制特点的是()。…[通俗易懂]
- java出现中文乱码_Java开发中中文乱码总结
- java dom4j生成xml格式化_Java DOM4J方式生成XML的方法「建议收藏」
- 【说站】java反射调用方法
- java 获取当前时间的三种方法_java获取单层文件夹大小
- java notifyall_Java Thread notifyAll()方法[通俗易懂]
- java date当前时间_JAVA中获取当前系统时间
- php getrealpath,java_java 获取路径的各种方法(总结),(1)、request.getRealPath(“/”);//不推 – phpStudy…
- java字符串分割split_js的sort排序方法
- java webservice接口开发教程_JAVA入门教程
- 【已解决】三种解决方法:Cannot deserialize value of type `java.util.Date` from String
- Java Socket实现Redis客户端的详细说明
- 运行参数Linux 下修改 Java 运行参数的指南(linux修改java)
- Java Map.values()方法:获取Map集合中的所有键值对象
- Java DriverManager.getConnection()方法:获取数据库连接
- Java轻松使用Redis实现数据高效存储(java使用redis)
- 构建Java应用程序中Redis集群的方法(java连redis集群)
- 深入学习:Linux下Java环境建设与配置(linux下java环境)
- 进程Linux下创建多个Java进程的简易方法(linux 多个java)
- Java编程在Linux上的应用(java编程 linux)
- Java实现嵌入式MySQL的新解决方案(java嵌入式mysql)
- Java反射获取类详细信息的常用方法总结
- 使用java获取md5值的两种方法
- JAVA读取文件夹大小的几种方法实例