What is it?
It is a library that allows the parameter names of non-private methods and constructors to be accessed at runtime. Normally this information is dropped by the compiler. In effect, methods like doSometing(mypkg.Person toMe) currently look like doSomething(mypackage.Person ???) to people using Java’s reflection to inspect methods.
项目主页:https://github.com/paul-hammant/paranamer
如何在运行时获取java方法参数名称?
- 由于jdk的反射方式,未提供获取参数名的方法
- Java的字节码文件默认不存储参数名称。在使用javac编译时,如果开启-g:{vars}选项,可以增加Local variable debugging information。对java方法,参数实际是按照局部变量来存储的,所以可以获取参数名称;但对于java接口中的方法声明,这种方法就无法获取参数名称。
Paranamer专门用来解决获取参数名的问题。其原理是在编译阶段,修改.class文件,在类或接口的字节码文件中增加一个字符串常量,这个常量保存了所有的方法声明信息,包括方法名、参数类型、参数名称。这样在运行时,class loader加载类文件以后,使用Paranamer的api去读取这个字符串,就可以获取参数名称。加上java反射,实际上可以把源代码重现出来。
这个工具可以用来实现代码生成器。其缺点在于,它需要修改源项目的build步骤。据其项目主页说明,Java 8已经加入存储参数名称的功能。
|
|
踩过的坑
需求:通过java的反射获取method,使用paranamer获取method的参数名称。
诡异之处:使用Paranamer paranamer = new CachingParanamer()l.ookupParameterNames(method);无法正常获取方法的变量名称。
一个简单的java类,请注意使用了import .* 的方式
|
|
使用paranamer-maven-plugin编译之后如下:
|
|
仔细观察可以发现生成的__PARANAMER_DATA常量中,并未包含对象类型变量的具体package路径,此时使用new CachingParanamer()l.ookupParameterNames(method)无法正常获取方法的变量名称。
去掉import .* 的方式之后,再次编译,常量中包含了对象类型变量具体的package路径,此时可成功获取方法的变量名称。
|
|