前言
大家都知道隨著java8的使用,在相應的方法簽名中增加了新的對象Parameter,用於表示特定的參數信息,通過它的getName可以獲取相應的參數名.即像在代碼中編寫的,如命名為username,那麼在前台進行傳參時,即不需要再編寫如@Parameter("username")類的註解,而直接就能進行按名映射.
如下的代碼參考所示:
public class T { private interface T2 { void method(String username, String password); } public static void main(String[] args) throws Exception { System.out.println(T.class.getMethod("main", String[].class).getParameters()[0].getName()); System.out.println(T2.class.getMethod("method", String.class, String.class).getParameters()[0].getName()); System.out.println(T2.class.getMethod("method", String.class, String.class).getParameters()[1].getName()); } }
按java8之前,也可以透過一些手段拿到參數名稱資訊,只不過方式不同而已.如透過spring mvc中的ParameterMethodNameResolver在之前的版本中也可以正常工作.不過需要特別的編譯而已.這裡面起作用的即是 LocalVariableTable 和 MethodParameters,中文編譯為本地變量表和方法參數表.
LocalVariableTable 本地變量表
按jvm規範所述,本地變量表存在於Code屬性中,而Code屬性即又是methodInfo的屬性.可以理解為,當一個方法有方法體時,就會出現相應的Code屬性,而且在code屬性中,除具體的執行代碼外,還會有其它的信息.如LineNumberTable (用於描述每一行程式碼所在的位置).
本地變數表屬於在方法中偵錯資訊的一部分,因此預設情況下這些資訊是不會產生在class檔案當中的.需要開啟-g 或-g: vars 開關.還好,對於ide或者是maven編譯來說,這些開關都是默認開啟的.在ide中,可以通過設置(generate debugging info 針對idea)來控制(默認打勾).在maven中,通過透過插件maven-compiler-plugin 中的debug或debugLevel來控制是否輸出(預設值是true).
本地變數表在javap之後,如下所示:
//非静态方法 LocalVariableTable: Start Length Slot Name Signature 0 1 0 this LT; 0 1 1 count J 0 1 3 name Ljava/lang/String; //静态方法 LocalVariableTable: Start Length Slot Name Signature 0 101 0 args [Ljava/lang/String;
本地變數表不僅保存了參數資訊,也保存在整個方法體中可能會使用的臨時變數,如聲明的int i等.並且如上所示,表示方法和非靜態方法,在第一位還有this變數的區別.因此,可以透過讀取參數個數(method.getParameterCount),然後再根據方法簽名,讀取本地變數表中指定個數的參數資訊即可.
需要注意的是,在上圖中,如果參數為long或double ,其slot佔位為2個,在透過slot來獲取參數資訊時,需要考慮參數的類型資訊.
介面方法由於沒有code屬性,因此也沒有本地變數表,拿到一個介面的方法定義,通過本地變數表是不能取得對應的參數名稱的
MethodParameters 方法參數表
方法參數表是在1.8之後引入的,因此只是使用jdk8編譯產生的class檔案才有此資訊. 與本地變數表不同,它是屬於MethodInfo屬性的,即它是與Code屬性同一級別的.不管是接口方法還是普通的方法,都是有此屬性的.因此,即使是接口方法,也可以獲取相應的參數信息.
預設情況下,class中是沒有此資訊的.需要使用特殊的編譯參數-parameters 才能產生,並且在ide和maven中,也預設不會產生此資訊.在idea中,需要在java additional line parameters中增加此編譯參數.在maven中,也需要在maven-compiler-plugin的compilerArgs參數中增加此參數才行.
方法參數表在javap之後,表現為如下形式:
//非静态方法 MethodParameters: Name Flags count name //静态方法 MethodParameters: Name Flags args
可以看出,無論是否靜態,在參數表中,只會出現用於描述參數的信息.後面的Flags參數用於一些特殊的場景,比如final參數用於方法改寫等.
可使用的一些工具
除使用原生的api,以及spring工具包,還有其它一些工具都可以拿到參數名資訊.在spring體系中,用於描述參數名的接口為 ParameterNameDiscoverer.通過它可以獲取相應的參數名信息. 除此之外, com.thoughtworks.paranamer:paranamer 這一工具包中的Paranamer 也可以同樣進行相應信息的處理. 不過對於jdk8的methodParameters支持度還不是很高,用戶可以通過擴展它來達到自己的目的.
總結
以上就是為大家總結的Java獲取程式碼中方法參數名稱資訊的方法,希望對大家學習或使用Java帶來一定的幫助,如果有疑問大家可以留言交流。
更多Java取得程式碼中方法參數名稱資訊的方法相關文章請關注PHP中文網!