在Java8中,可以使用 java.lang.reflect.Executable.getParameters 获取方法或构造函数的形参名称,(Method 和 Constructor 类扩展了 Executable 类,因此继承了 Executable.getParameters 方法)。
但是 .class 文件默认不存储形式参数名称。因为许多生成和使用类文件的工具不希望具有更大静态和动态 Footprint^1的包含参数名称的 .class 文件。尤其是这些工具处理更大的 .class 文件时,Java 虚拟机 (JVM) 将使用更多内存。此外,某些参数名称(如 secret 或 password)可能会暴露有关安全敏感方法的信息。^2
因此,要将形式参数名称存储在特定的 .class 文件中,从而使反射 API 能够检索形式参数名称,请使用 javac 编译器的 -parameters 选项编译源文件。
在maven中,可以在pom.xml中声明这个选项^3
1 2 3 4 5 6 7 8 9 10
| <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgument>-parameters</compilerArgument> </configuration> </plugin>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Test public void whenGetConstructorParams_thenOk() throws NoSuchMethodException, SecurityException { Parameter[] parameters = Person.class.getConstructor(String.class) .getParameters();
Assertions.assertTrue(Arrays.stream(parameters) .allMatch(parameter -> "fullName".equals(parameter.getName()))); }
@Test public void whenGetMethodParams_thenOk() throws NoSuchMethodException, SecurityException { Parameter[] parameters = Person.class.getMethod("setFullName", String.class) .getParameters();
Assertions.assertTrue(Arrays.stream(parameters) .allMatch(parameter -> "fullName".equals(parameter.getName()))); }
public static class Person { private String fullName;
public Person(String fullName) { this.fullName = fullName; }
public void setFullName(String fullName) { this.fullName = fullName; }
}
|
实际的使用场景:mybatis的 org.apache.ibatis.reflection.ParamNameUtil#getParameterNames 方法,用来获取真实的参数名。通过使用-parameters参数,就不需要在Mapper中使用@Param注解指定参数别名了。