在有些场景下,我们有可能想在程序中获取一个方法参数的名称。
但是,对于Java这样的“编译”型语言来说,并没有直接的API可以调用。
其实很容易理解,当Java源代码被编译成字节码后,方法的签名可能不会被保存下来,也就无从获取方法的参数名称了。
虽然官方没有提供直接的解决方案,但是民间偏方还是有的。 思路就是:字节码解析,通过解析class文件,获取方法签名中的参数名称。
既然还是解析字节码,那么能否成功依然受到Java编译指令的影响。
也就是说,只有在编译的时候开启了debug信息,这样编译好的字节码中才会完整保留方法的参数名。
目前,比较流行的字节码处理框架是ASM,但是 com.thoughtworks.paranamer 这个基于ASM的框架,提供了一个方便的解决方案。
我们看看它是怎么实现获取参数名称的。
import java.lang.reflect.Method;
import com.thoughtworks.paranamer.BytecodeReadingParanamer;
import com.thoughtworks.paranamer.Paranamer;
public class DetectParameterNames {
public String[] detectParameterNames(String name1, String name2)
throws Exception {
Method method = getClass().getDeclaredMethod("detectParameterNames",
String.class, String.class);
if (method != null) {
Paranamer paranamer = new BytecodeReadingParanamer();
String[] parameterNames = paranamer.lookupParameterNames(method);
return parameterNames;
}
return null;
}
public static void main(String[] args) throws Exception {
String[] parameterNames = new DetectParameterNames()
.detectParameterNames(null, null);
for (String parameterName : parameterNames) {
System.out.println(parameterName);
}
}
}
在命令行编译的时候,需要-g以保留debug信息
如果是eclipse,需要在编译的时候勾选这三行,具体作用写的非常明确。
总结:虽然说这个“民间偏方”确实能够解决问题,不过依赖编译时选择“生成所有调试信息”。这样脆弱的强依赖,非常容易出现问题。所以,此方式看起来并不是一个非常好的选择,尤其对于商业使用。