如何获取对象构造函数的参数名称(reflection)?

说我以某种方式得到了另一个类的对象引用:

Object myObj = anObject; 

现在我可以得到这个对象的类:

 Class objClass = myObj.getClass(); 

现在,我可以获得此类的所有构造函数:

 Constructor[] constructors = objClass.getConstructors(); 

现在,我可以循环每个构造函数:

 if (constructors.length > 0) { for (int i = 0; i < constructors.length; i++) { System.out.println(constructors[i]); } } 

这已经给了我构造函数的一个很好的总结,例如构造函数public Test(String paramName)显示为public Test(java.lang.String)

但是,我想获取参数的名称,而不是给我类类型。在这种情况下,“paramName”。 我该怎么办? 我尝试了以下但没有成功:

 if (constructors.length > 0) { for (int iCon = 0; iCon  0) { for (int iPar = 0; iPar < params.length; iPar++) { Field fields[] = params[iPar].getDeclaredFields(); for (int iFields = 0; iFields < fields.length; iFields++) { String fieldName = fields[i].getName(); System.out.println(fieldName); } } } } } 

不幸的是,这并没有给我预期的结果。 谁能告诉我应该怎么做或者我做错了什么? 谢谢!

编译后此信息将丢失,无法在运行时检索。

正如对Roman回答的评论中所提到的 ,如果编译器包含调试符号, 可以检索参数名称,但不是通过标准Java Reflection API。 下面是一个示例,说明如何使用ASM字节码库通过调试符号获取参数名称:

 /** * Returns a list containing one parameter name for each argument accepted * by the given constructor. If the class was compiled with debugging * symbols, the parameter names will match those provided in the Java source * code. Otherwise, a generic "arg" parameter name is generated ("arg0" for * the first argument, "arg1" for the second...). * * This method relies on the constructor's class loader to locate the * bytecode resource that defined its class. * * @param constructor * @return * @throws IOException */ public static List getParameterNames(Constructor constructor) throws IOException { Class declaringClass = constructor.getDeclaringClass(); ClassLoader declaringClassLoader = declaringClass.getClassLoader(); Type declaringType = Type.getType(declaringClass); String constructorDescriptor = Type.getConstructorDescriptor(constructor); String url = declaringType.getInternalName() + ".class"; InputStream classFileInputStream = declaringClassLoader.getResourceAsStream(url); if (classFileInputStream == null) { throw new IllegalArgumentException("The constructor's class loader cannot find the bytecode that defined the constructor's class (URL: " + url + ")"); } ClassNode classNode; try { classNode = new ClassNode(); ClassReader classReader = new ClassReader(classFileInputStream); classReader.accept(classNode, 0); } finally { classFileInputStream.close(); } @SuppressWarnings("unchecked") List methods = classNode.methods; for (MethodNode method : methods) { if (method.name.equals("") && method.desc.equals(constructorDescriptor)) { Type[] argumentTypes = Type.getArgumentTypes(method.desc); List parameterNames = new ArrayList(argumentTypes.length); @SuppressWarnings("unchecked") List localVariables = method.localVariables; for (int i = 0; i < argumentTypes.length; i++) { // The first local variable actually represents the "this" object parameterNames.add(localVariables.get(i + 1).name); } return parameterNames; } } return null; } 

此示例使用ASM库的树API 。 如果速度和内存很宝贵,您可以重构示例以使用其访问者API 。

试试https://github.com/paul-hammant/paranamer

哦,为了善良,所以,真的,你要让我输入至少30个字符来编辑现有答案以使其正确。