摘要:前言在之前編譯是不會把構造器和方法的參數名編譯進中,如果需要獲取參數名,可以在方法上加上注解,反射獲取注解的值從而獲取參數名,比如的和。帶在中添加命令行在后面加運行結果構造器方法一方法二方法三方法四這樣就把參數名給打印出來了,為。
前言
在JDK8之前javac編譯是不會把構造器和方法的參數名編譯進class中,如果需要獲取參數名,可以在方法上加上注解,反射獲取注解的值從而獲取參數名,比如Jackson的@JsonCreator和@JsonProperty 。而JDK8新增了這一個功能,可以直接調用java.lang.reflect.Parameter.getName()獲取到,前提是javac需要添加-parameters這個參數。通常來說不建議這樣做,因為這會增大.class和在JVM中會占用更多的內存。
正文 代碼直接上代碼。
用來打印類信息
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不帶-parameters{ 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 listParam) { return listParam.isEmpty(); } public void genericMethod(T[] a, Collection c) { System.out.println("Length of array: " + a.length); System.out.println("Size of collection: " + c.size()); } }
不帶-parameters運行結果:
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) 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 void ExampleMethods.genericMethod(T[],java.util.Collection ) 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。
帶-parametersmaven在pom.xml中添加
org.apache.maven.plugins maven-compiler-plugin 8 -parameters
命令行在javac 后面加 -parameters
運行結果
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) 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 void ExampleMethods.genericMethod(T[],java.util.Collection ) 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。
留個問題出于好奇,以十六進制打開ExampleMethods的class文件,maven項目在idea中build出來的class不管有沒有帶-parameters都會把參數名編譯進去,但是多了MethodParameters這幾個字眼。如下圖:
然后嘗試直接用javac -parameters編譯,打開后
很明顯是沒有把參數名編譯進去的。
好像找不到idea執行build的時候執行了什么,所有我猜測控制java.lang.reflect.Parameter.getName()返回是否真實的參數名就是在于MethodParameters這詞,在jvm加載class時識別是否有MethodParameters,而決定是否加載參數名。
這僅是猜測,望大家相告是其真正的原理。
文中也可能存在錯誤,也望大家指出。
上述代碼全部來自#參考資料中的Obtaining Names of Method Parameters
參考資料Obtaining Names of Method Parameters
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76827.html
摘要:通過反射獲取帶參無返回值成員方法并使用設置安全檢查,訪問私有構造函數必須創建實例這種不行,注意和方法需要傳遞參數測試復制這個功能獲取私有方法,同樣注意和的區別賦予訪問權限調用方法。 反射 目錄介紹 1.反射概述 1.1 反射概述 1.2 獲取class文件對象的三種方式 1.3 反射常用的方法介紹 1.4 反射的定義 1.5 反射的組成 1.6 反射的作用有哪些 2.反射的...
摘要:有一個參數的構造方法姓名有多個參數的構造方法姓名年齡這的執行效率有問題,以后解決。私有構造方法私有的構造方法年齡反射獲取對象的三種方式通過對象名方法獲取通過類名方式獲得通過方法獲得在運行期間,一個類,只有一個對象產生。 原文地址 反射簡單來說,就是動態加載對象,并對對象進行剖析。在Java中的反射機制是指在運行狀態中,對于任意一個類,都能夠知道并獲取這個類的所有屬性和方法。 Java反...
摘要:不包含父類或父接口的方法返回,根據方法名和類型獲取。類或接口的及父類父接口公共成員方法。是的返回方法名,不包括修飾符,參數和返回值。打印打印拋出因為的訪問權限為拋出,因為是父類的方法。 反射機制呢就是在程序運行時,動態的獲取類(class),類的方法(method)屬性(field)等。主要的注意點就是程序運行時動態的獲取。這里主要是從代碼的角度來講解Java反射。在使用中我們用的較多...
摘要:通過反射獲取無參構造方法并使用得到無參構造方法獲取所有的修飾的構造方法。如果方法沒有返回值,返回的是反射獲取空參數成員方法并運行代碼演示反射獲取成員方法并運行獲取對象中的成員方法獲取的是文件中的所有公共成員方法包括繼承的類是描述 01類加載器 * A.類的加載 當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,連接,初始化三步來實現對這個類進行初始化。 ? ...
摘要:反射機制是什么反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法對于任意一個對象,都能夠調用它的任意一個方法和屬性這種動態獲取的信息以及動態調用對象的方法的功能稱為語言的反射機制反射機制能做什么反射機制主要提供了以下功 反射機制是什么 反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種...
閱讀 2056·2021-10-08 10:04
閱讀 3086·2021-09-22 10:02
閱讀 2236·2019-08-30 15:56
閱讀 829·2019-08-30 15:54
閱讀 925·2019-08-30 15:54
閱讀 1280·2019-08-30 15:53
閱讀 2512·2019-08-30 11:21
閱讀 3561·2019-08-30 10:56