代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
Java
】
获取方法参数名称
作者:
wendal
/ 发布于
2013/9/2
/
961
获取方法行参名称,针对没有优化过的代码
package org.youyou.utils; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 通过读取Class文件,获得方法形参名称列表 * * */ public class MethodParamNamesScanner { /** * 获取Method的形参名称列表 * * @param method 需要解析的方法 * @return 形参名称列表, 如果没有调试信息, 将返回null */ public static List<String> getParamNames(Method method) { try { int size = method.getParameterTypes().length; if (size == 0) return new ArrayList<String>(0); List<String> list = getParamNames(method.getDeclaringClass()).get(getKey(method)); if (list != null && list.size() != size) return list.subList(0, size); return list; } catch (Throwable e) { throw new RuntimeException(e); } } /** * 获取Constructor的形参名称列表 * * @param constructor 需要解析的构造函数 * @return 形参名称列表, 如果没有调试信息, 将返回null */ public static List<String> getParamNames(Constructor<?> constructor) { try { int size = constructor.getParameterTypes().length; if (size == 0) return new ArrayList<String>(0); List<String> list = getParamNames(constructor.getDeclaringClass()).get(getKey(constructor)); if (list != null && list.size() != size) return list.subList(0, size); return list; } catch (Throwable e) { throw new RuntimeException(e); } } //--------------------------------------------------------------------------------------------------- /** * 获取一个类的所有方法/构造方法的形参名称Map * * @param klass 需要解析的类 * @return 所有方法/构造方法的形参名称Map * @throws IOException 如果有任何IO异常,不应该有,如果是本地文件,那100%遇到bug了 */ public static Map<String, List<String>> getParamNames(Class<?> klass) throws IOException { InputStream in = klass.getResourceAsStream("/" + klass.getName().replace('.', '/') + ".class"); return getParamNames(in); } public static Map<String, List<String>> getParamNames(InputStream in) throws IOException { DataInputStream dis = new DataInputStream(new BufferedInputStream(in)); Map<String, List<String>> names = new HashMap<String, List<String>>(); Map<Integer, String> strs = new HashMap<Integer, String>(); dis.skipBytes(4);//Magic dis.skipBytes(2);//副版本号 dis.skipBytes(2);//主版本号 //读取常量池 int constant_pool_count = dis.readUnsignedShort(); for (int i = 0; i < (constant_pool_count - 1); i++) { byte flag = dis.readByte(); switch (flag) { case 7://CONSTANT_Class: dis.skipBytes(2); break; case 9://CONSTANT_Fieldref: case 10://CONSTANT_Methodref: case 11://CONSTANT_InterfaceMethodref: dis.skipBytes(2); dis.skipBytes(2); break; case 8://CONSTANT_String: dis.skipBytes(2); break; case 3://CONSTANT_Integer: case 4://CONSTANT_Float: dis.skipBytes(4); break; case 5://CONSTANT_Long: case 6://CONSTANT_Double: dis.skipBytes(8); i++;//必须跳过一个,这是class文件设计的一个缺陷,历史遗留问题 break; case 12://CONSTANT_NameAndType: dis.skipBytes(2); dis.skipBytes(2); break; case 1://CONSTANT_Utf8: int len = dis.readUnsignedShort(); byte[] data = new byte[len]; dis.read(data); strs.put(i + 1, new String(data, "UTF-8"));//必然是UTF8的 break; case 15://CONSTANT_MethodHandle: dis.skipBytes(1); dis.skipBytes(2); break; case 16://CONSTANT_MethodType: dis.skipBytes(2); break; case 18://CONSTANT_InvokeDynamic: dis.skipBytes(2); dis.skipBytes(2); break; default: throw new RuntimeException("Impossible!! flag=" + flag); } } dis.skipBytes(2);//版本控制符 dis.skipBytes(2);//类名 dis.skipBytes(2);//超类 //跳过接口定义 int interfaces_count = dis.readUnsignedShort(); dis.skipBytes(2 * interfaces_count);//每个接口数据,是2个字节 //跳过字段定义 int fields_count = dis.readUnsignedShort(); for (int i = 0; i < fields_count; i++) { dis.skipBytes(2); dis.skipBytes(2); dis.skipBytes(2); int attributes_count = dis.readUnsignedShort(); for (int j = 0; j < attributes_count; j++) { dis.skipBytes(2);//跳过访问控制符 int attribute_length = dis.readInt(); dis.skipBytes(attribute_length); } } //开始读取方法 int methods_count = dis.readUnsignedShort(); for (int i = 0; i < methods_count; i++) { dis.skipBytes(2); //跳过访问控制符 String methodName = strs.get(dis.readUnsignedShort()); String descriptor = strs.get(dis.readUnsignedShort()); short attributes_count = dis.readShort(); for (int j = 0; j < attributes_count; j++) { String attrName = strs.get(dis.readUnsignedShort()); int attribute_length = dis.readInt(); if ("Code".equals(attrName)) { //形参只在Code属性中 dis.skipBytes(2); dis.skipBytes(2); int code_len = dis.readInt(); dis.skipBytes(code_len); //跳过具体代码 int exception_table_length = dis.readUnsignedShort(); dis.skipBytes(8 * exception_table_length); //跳过异常表 int code_attributes_count = dis.readUnsignedShort(); for (int k = 0; k < code_attributes_count; k++) { int str_index = dis.readUnsignedShort(); String codeAttrName = strs.get(str_index); int code_attribute_length = dis.readInt(); if ("LocalVariableTable".equals(codeAttrName)) {//形参在LocalVariableTable属性中 int local_variable_table_length = dis.readUnsignedShort(); List<String> varNames = new ArrayList<String>(local_variable_table_length); for (int l = 0; l < local_variable_table_length; l++) { dis.skipBytes(2); dis.skipBytes(2); String varName = strs.get(dis.readUnsignedShort()); dis.skipBytes(2); dis.skipBytes(2); if (!"this".equals(varName)) //非静态方法,第一个参数是this varNames.add(varName); } names.put(methodName + "," + descriptor, varNames); } else dis.skipBytes(code_attribute_length); } } else dis.skipBytes(attribute_length); } } dis.close(); return names; } /** * 传入Method或Constructor,获取getParamNames方法返回的Map所对应的key */ public static String getKey(Object obj) { StringBuilder sb = new StringBuilder(); if (obj instanceof Method) { sb.append(((Method) obj).getName()).append(','); getDescriptor(sb, (Method) obj); } else if (obj instanceof Constructor) { sb.append("<init>,"); //只有非静态构造方法才能用有方法参数的,而且通过反射API拿不到静态构造方法 getDescriptor(sb, (Constructor<?>) obj); } else throw new RuntimeException("Not Method or Constructor!"); return sb.toString(); } public static void getDescriptor(StringBuilder sb, Method method) { sb.append('('); for (Class<?> klass : method.getParameterTypes()) getDescriptor(sb, klass); sb.append(')'); getDescriptor(sb, method.getReturnType()); } public static void getDescriptor(StringBuilder sb, Constructor<?> constructor) { sb.append('('); for (Class<?> klass : constructor.getParameterTypes()) getDescriptor(sb, klass); sb.append(')'); sb.append('V'); } /** * 本方法来源于ow2的asm库的Type类 */ public static void getDescriptor(final StringBuilder buf, final Class<?> c) { Class<?> d = c; while (true) { if (d.isPrimitive()) { char car; if (d == Integer.TYPE) { car = 'I'; } else if (d == Void.TYPE) { car = 'V'; } else if (d == Boolean.TYPE) { car = 'Z'; } else if (d == Byte.TYPE) { car = 'B'; } else if (d == Character.TYPE) { car = 'C'; } else if (d == Short.TYPE) { car = 'S'; } else if (d == Double.TYPE) { car = 'D'; } else if (d == Float.TYPE) { car = 'F'; } else /* if (d == Long.TYPE) */ { car = 'J'; } buf.append(car); return; } else if (d.isArray()) { buf.append('['); d = d.getComponentType(); } else { buf.append('L'); String name = d.getName(); int len = name.length(); for (int i = 0; i < len; ++i) { char car = name.charAt(i); buf.append(car == '.' ? '/' : car); } buf.append(';'); return; } } } }
试试其它关键字
参数名称
同语言下
.
List 切割成几份 工具类
.
一行一行读取txt的内容
.
Java PDF转换成图片并输出给前台展示
.
java 多线程框架
.
double类型如果小数点后为零则显示整数否则保留两位小
.
将图片转换为Base64字符串公共类抽取
.
sqlParser 处理SQL(增删改查) 替换schema 用于多租户
.
JAVA 月份中的第几周处理 1-7属于第一周 依次类推 29-
.
java计算两个经纬度之间的距离
.
输入时间参数计算年龄
可能有用的
.
C#实现的html内容截取
.
List 切割成几份 工具类
.
SQL查询 多列合并成一行用逗号隔开
.
一行一行读取txt的内容
.
C#动态修改文件夹名称(FSO实现,不移动文件)
.
c# 移动文件或文件夹
.
c#图片添加水印
.
Java PDF转换成图片并输出给前台展示
.
网站后台修改图片尺寸代码
.
处理大图片在缩略图时的展示
wendal
贡献的其它代码
(
1
)
.
获取方法参数名称
Copyright © 2004 - 2024 dezai.cn. All Rights Reserved
站长博客
粤ICP备13059550号-3