0%

Java语言新特性漫谈:Java 8之方法参数反射

本文是《Java语言新特性漫谈》系列文章中的一篇,该系列文章主要探讨各 Java 版本的语言特性方面的增强更新。

Java 8 之前,反射对方法参数的支持是有限的,某些信息甚至通过反射根本无法获取到。对此,Java 8 添加了一些增强特性。

主要的源码级改动是为 MethodConstructor 类新增了父类 java.lang.reflect.Executable,该父类提供了方法 getParameters() 返回参数数组。注意这个参数数组元素对应的 java.lang.reflect.Parameter 类也是 Java 8 新增的。通过它可以得到参数的更多信息,比如:名称、修饰符等等。

下面的测试类展示了如何获取参数名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MethodParameterReflectionTest {
public void doSth(String justName) {
System.out.println(justName);
}

@Test
public void testGetMethodParameterName() throws NoSuchMethodException {
Method doSthMethod = MethodParameterReflectionTest.class.getMethod("doSth", String.class);
Parameter[] params = doSthMethod.getParameters();
Parameter param = params[0];
System.out.println(param.isNamePresent() + ": " + param.getName());
}
}

But,通常情况下得到的参数名应该形如 arg0。原因在于,形参名默认是不会写入 .class 文件,如果要,则需要添加编译器选项 -parameters

IDEA 中,在 Java 编译器设置中为项目(即 Module)配置 -parameters 编译器选项即可。如下图:

IDEA Settings

由此可知,Parameter.getName() 方法能否返回源码中的形参名,取决于编译器选项配置。因此,在获取形参名前,需要通过 Parameter.isNamePresent() 方法来判断,形参名是否存储在 .class 文件中。以此确定取得的形参名是真实名称还是合成名。