Java獲取代碼中方法參數(shù)名信息的方法
前言
大家都知道隨著java8的使用,在相應(yīng)的方法簽名中增加了新的對(duì)象Parameter,用于表示特定的參數(shù)信息,通過(guò)它的getName可以獲取相應(yīng)的參數(shù)名.即像在代碼中編寫(xiě)的,如命名為username,那么在前臺(tái)進(jìn)行傳參時(shí),即不需要再編寫(xiě)如@Parameter("username")類(lèi)的注解,而直接就能進(jìn)行按名映射.
如下的代碼參考所示:
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之前,也可以通過(guò)一些手段拿到參數(shù)名信息,只不過(guò)方式不同而已.如通過(guò)spring mvc中的ParameterMethodNameResolver
在之前的版本中也可以正常工作.不過(guò)需要特別的編譯而已.這里面起作用的即是 LocalVariableTable
和 MethodParameters
,中文編譯為本地變量表和方法參數(shù)表.
LocalVariableTable 本地變量表
按jvm規(guī)范所述,本地變量表存在于Code屬性中,而Code屬性即又是methodInfo的一個(gè)屬性.可以理解為,當(dāng)一個(gè)方法有方法體時(shí),就會(huì)出現(xiàn)相應(yīng)的Code屬性,而且在code屬性中,除具體的執(zhí)行代碼外,還會(huì)有其它的信息.如LineNumberTable(用于描述每一行代碼所在的位置).
本地變量表屬于在方法中調(diào)試信息的一部分,因此默認(rèn)情況下這些信息是不會(huì)生成在class文件當(dāng)中的.需要開(kāi)啟 -g 或 -g:vars 開(kāi)關(guān).還好,對(duì)于ide或者是maven編譯來(lái)說(shuō),這些開(kāi)關(guān)都是默認(rèn)開(kāi)啟的.在ide中,可以通過(guò)設(shè)置(generate debugging info 針對(duì)idea)來(lái)控制(默認(rèn)打勾).在maven中,通過(guò)通過(guò)插件 maven-compiler-plugin 中的debug或debugLevel來(lái)控制是否輸出(默認(rèn)值是true).
本地變量表在javap之后,如下所示:
//非靜態(tài)方法 LocalVariableTable: Start Length Slot Name Signature 0 1 0 this LT; 0 1 1 count J 0 1 3 name Ljava/lang/String; //靜態(tài)方法 LocalVariableTable: Start Length Slot Name Signature 0 101 0 args [Ljava/lang/String;
本地變量表不僅保存了參數(shù)信息,還保存在在整個(gè)方法體中可能會(huì)使用的臨時(shí)變量,如聲明的int i等.并且如上所示,表示方法和非靜態(tài)方法,在第一位還有this變量的區(qū)別.因此,可以通過(guò)讀取參數(shù)個(gè)數(shù)(method.getParameterCount
),然后再根據(jù)方法簽名,讀取本地變量表中指定個(gè)數(shù)的參數(shù)信息即可.
需要注意的是,在上圖中,如果參數(shù)為long或double,其slot占位為2個(gè),在通過(guò)slot來(lái)獲取參數(shù)信息時(shí),需要考慮參數(shù)的類(lèi)型信息.
接口方法由于沒(méi)有code屬性,因此也沒(méi)有本地變量表,拿到一個(gè)接口的方法定義,通過(guò)本地變量表是不能獲取到相應(yīng)的參數(shù)名的
MethodParameters 方法參數(shù)表
方法參數(shù)表是在1.8之后引入的,因此只是使用jdk8編譯生成的class文件才有此信息. 與本地變量表不同,它是屬于MethodInfo屬性的,即它是與Code屬性同一級(jí)別的.不管是接口方法還是普通的方法,都是有此屬性的.因此,即使是接口方法,也可以獲取相應(yīng)的參數(shù)信息.
默認(rèn)情況下,class中是沒(méi)有此信息的.需要使用特殊的編譯參數(shù) -parameters 才能生成,并且在ide和maven中,也默認(rèn)不會(huì)生成此信息.在idea中,需要在java additional line parameters中增加此編譯參數(shù).在maven中,也需要在maven-compiler-plugin的compilerArgs
參數(shù)中增加此參數(shù)才行.
方法參數(shù)表在javap之后,表現(xiàn)為如下形式:
//非靜態(tài)方法 MethodParameters: Name Flags count name //靜態(tài)方法 MethodParameters: Name Flags args
可以看出,無(wú)論是否靜態(tài),在參數(shù)表中,只會(huì)出現(xiàn)用于描述參數(shù)的信息.后面的Flags參數(shù)用于一些特殊的場(chǎng)景,比如final
參數(shù)用于方法改寫(xiě)等.
可使用的一些工具
除使用原生的api,以及spring工具包,還有其它一些工具都可以拿到參數(shù)名信息.在spring體系中,用于描述參數(shù)名的接口為 ParameterNameDiscoverer
.通過(guò)它可以獲取相應(yīng)的參數(shù)名信息. 除此之外, com.thoughtworks.paranamer:paranamer
這一工具包中的Paranamer 也可以同樣進(jìn)行相應(yīng)信息的處理. 不過(guò)對(duì)于jdk8的methodParameters支持度還不是很高,使用者可以通過(guò)擴(kuò)展它來(lái)達(dá)到自己的目的.
總結(jié)
以上就是為大家總結(jié)的Java獲取代碼中方法參數(shù)名信息的方法,希望對(duì)大家學(xué)習(xí)或使用Java帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
- java自定義注解實(shí)現(xiàn)前后臺(tái)參數(shù)校驗(yàn)的實(shí)例
- 關(guān)于java中可變長(zhǎng)參數(shù)的定義及使用方法詳解
- java向多線程中傳遞參數(shù)的三種方法詳細(xì)介紹
- java根據(jù)方法名稱(chēng)取得反射方法的參數(shù)類(lèi)型示例
- Java方法的可變參數(shù)類(lèi)型實(shí)例分析
- Java方法參數(shù)是引用調(diào)用還是值調(diào)用?
- 在java代碼中獲取JVM參數(shù)的方法
- Java中final作用于變量、參數(shù)、方法及類(lèi)該如何處理
- Java方法能定義多少個(gè)參數(shù)你知道嗎
相關(guān)文章
Java springboot探究配置文件優(yōu)先級(jí)
在springboot項(xiàng)目中,我們可以通過(guò)在yml文件中設(shè)置變量,再通過(guò)@Value注解來(lái)獲得這個(gè)變量并使用,但如果這個(gè)項(xiàng)目已經(jīng)部署到服務(wù)器上,我們想更改這個(gè)數(shù)據(jù)了需要怎么做呢,其實(shí)在springboot項(xiàng)目中,配置文件是有優(yōu)先級(jí)的2023-04-04如何使用IDEA創(chuàng)建MAPPER模板過(guò)程圖解
這篇文章主要介紹了如何使用IDEA創(chuàng)建MAPPER模板,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Java多線程實(shí)現(xiàn)之Callable詳解
這篇文章主要介紹了Java多線程實(shí)現(xiàn)之Callable詳解,Callable是一個(gè)接口,用于實(shí)現(xiàn)多線程,與實(shí)現(xiàn)Runnable類(lèi)似,但是功能更強(qiáng)大,通過(guò)實(shí)現(xiàn)Callable接口,我們需要重寫(xiě)call()方法,該方法可以在任務(wù)結(jié)束后提供一個(gè)返回值,需要的朋友可以參考下2023-08-08詳細(xì)聊聊RabbitMQ竟無(wú)法反序列化List問(wèn)題
這篇文章主要給大家介紹了關(guān)于RabbitMQ竟無(wú)法反序列化List的相關(guān)資料,文中通過(guò)示例代碼將問(wèn)題以及解決的過(guò)程介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-09-09Java實(shí)現(xiàn)Fibonacci(斐波那契)取余的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)Fibonacci取余的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03javafx tableview鼠標(biāo)觸發(fā)更新屬性詳解
這篇文章主要為大家詳細(xì)介紹了javafx tableview鼠標(biāo)觸發(fā)更新屬性的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Spring操作JdbcTemplate數(shù)據(jù)庫(kù)的方法學(xué)習(xí)
這篇文章主要為大家介紹了Spring操作JdbcTemplate數(shù)據(jù)庫(kù)方法學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Java Druid連接池與Apache的DBUtils使用教程
這篇文章主要介紹了Java Druid連接池與Apache的DBUtils使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-12-12