在JDK8以前javac編譯是不會把構造器和方法的參數名編譯進class中,若是須要獲取參數名,能夠在方法上加上註解,反射獲取註解的值從而獲取參數名,好比Jackson的@JsonCreator和@JsonProperty 。而JDK8新增了這一個功能,能夠直接調用java.lang.reflect.Parameter.getName()獲取到,前提是javac須要添加-parameters這個參數。一般來講不建議這樣作,由於這會增大.class和在JVM中會佔用更多的內存。html
直接上代碼。java
用來打印類信息
import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import static java.lang.System.out; public class MethodParameterSpy { private static final String fmt = "%24s: %s%n"; public static void printClassConstructors(Class c) { Constructor[] allConstructors = c.getConstructors(); out.format(fmt, "Number of constructors", allConstructors.length); for (Constructor currentConstructor : allConstructors) { printConstructor(currentConstructor); } Constructor[] allDeclConst = c.getDeclaredConstructors(); out.format(fmt, "Number of declared constructors", allDeclConst.length); for (Constructor currentDeclConst : allDeclConst) { printConstructor(currentDeclConst); } } public static void printClassMethods(Class c) { Method[] allMethods = c.getDeclaredMethods(); out.format(fmt, "Number of methods", allMethods.length); for (Method m : allMethods) { printMethod(m); } } public static void printConstructor(Constructor c) { out.format("%s%n", c.toGenericString()); Parameter[] params = c.getParameters(); out.format(fmt, "Number of parameters", params.length); for (int i = 0; i < params.length; i++) { printParameter(params[i]); } } public static void printMethod(Method m) { out.format("%s%n", m.toGenericString()); out.format(fmt, "Return type", m.getReturnType()); out.format(fmt, "Generic return type", m.getGenericReturnType()); Parameter[] params = m.getParameters(); for (int i = 0; i < params.length; i++) { printParameter(params[i]); } } public static void printParameter(Parameter p) { out.format(fmt, "Parameter class", p.getType()); out.format(fmt, "Parameter name", p.getName()); out.format(fmt, "Modifiers", p.getModifiers()); out.format(fmt, "Is implicit?", p.isImplicit()); out.format(fmt, "Is name present?", p.isNamePresent()); out.format(fmt, "Is synthetic?", p.isSynthetic()); } public static void main(String... args) { printClassConstructors(ExampleMethods.class); printClassMethods(ExampleMethods.class); } }
包含各類類型方法的類
import java.util.*; public class ExampleMethods<T> { public boolean simpleMethod(String stringParam, int intParam) { System.out.println("String: " + stringParam + ", integer: " + intParam); return true; } public int varArgsMethod(String... manyStrings) { return manyStrings.length; } public boolean methodWithList(List<String> listParam) { return listParam.isEmpty(); } public <T> void genericMethod(T[] a, Collection<T> c) { System.out.println("Length of array: " + a.length); System.out.println("Size of collection: " + c.size()); } }
不帶-parameters運行結果:apache
Number of constructors: 1 public ExampleMethods() Number of parameters: 0 Number of declared constructors: 1 # 構造器 public ExampleMethods() Number of parameters: 0 Number of methods: 4 # 方法一 public boolean ExampleMethods.simpleMethod(java.lang.String,int) Return type: boolean Generic return type: boolean Parameter class: class java.lang.String Parameter name: arg0 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false Parameter class: int Parameter name: arg1 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false # 方法二 public boolean ExampleMethods.methodWithList(java.util.List<java.lang.String>) Return type: boolean Generic return type: boolean Parameter class: interface java.util.List Parameter name: arg0 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false # 方法三 public <T> void ExampleMethods.genericMethod(T[],java.util.Collection<T>) Return type: void Generic return type: void Parameter class: class [Ljava.lang.Object; Parameter name: arg0 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false Parameter class: interface java.util.Collection Parameter name: arg1 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false # 方法四 public int ExampleMethods.varArgsMethod(java.lang.String...) Return type: int Generic return type: int Parameter class: class [Ljava.lang.String; Parameter name: arg0 Modifiers: 0 Is implicit?: false Is name present?: false Is synthetic?: false
能夠看出Parameter name全都是arg0~argN,由於參數名在編譯期已經丟失了。Is name present爲false。oracle
maven在pom.xml中添加
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> <compilerArgument>-parameters</compilerArgument> </configuration> </plugin> </plugins> </build>
命令行在javac 後面加 -parametersjvm
運行結果
Number of constructors: 1 public ExampleMethods() Number of parameters: 0 Number of declared constructors: 1 # 構造器 public ExampleMethods() Number of parameters: 0 Number of methods: 4 # 方法一 public boolean ExampleMethods.methodWithList(java.util.List<java.lang.String>) Return type: boolean Generic return type: boolean Parameter class: interface java.util.List Parameter name: listParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false # 方法二 public int ExampleMethods.varArgsMethod(java.lang.String...) Return type: int Generic return type: int Parameter class: class [Ljava.lang.String; Parameter name: manyStrings Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false # 方法三 public <T> void ExampleMethods.genericMethod(T[],java.util.Collection<T>) Return type: void Generic return type: void Parameter class: class [Ljava.lang.Object; Parameter name: a Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Parameter class: interface java.util.Collection Parameter name: c Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false # 方法四 public boolean ExampleMethods.simpleMethod(java.lang.String,int) Return type: boolean Generic return type: boolean Parameter class: class java.lang.String Parameter name: stringParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false Parameter class: int Parameter name: intParam Modifiers: 0 Is implicit?: false Is name present?: true Is synthetic?: false
這樣就把參數名給打印出來了,Is name present爲true。maven
出於好奇,以十六進制打開ExampleMethods的class文件,maven項目在idea中build出來的class無論有沒有帶-parameters都會把參數名編譯進去,可是多了MethodParameters這幾個字眼。以下圖:ide
而後嘗試直接用javac -parameters編譯,打開後ui
很明顯是沒有把參數名編譯進去的。idea
好像找不到idea執行build的時候執行了什麼,全部我猜想控制java.lang.reflect.Parameter.getName()返回是否真實的參數名就是在於MethodParameters這詞,在jvm加載class時識別是否有MethodParameters,而決定是否加載參數名。spa
這僅是猜想,望你們相告是其真正的原理。
文中也可能存在錯誤,也望你們指出。
上述代碼所有來自#參考資料中的Obtaining Names of Method Parameters