自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java如何獲取方法參數(shù)具體名稱?這是個好問題!

開發(fā) 后端
默認情況下,我們是無法獲取方法中參數(shù)名稱的。通過反射機制,也只能得到參數(shù)的順序以及一些沒有意義的變量:arg0、arg1等等。

默認情況下,我們是無法獲取方法中參數(shù)名稱的。通過反射機制,也只能得到參數(shù)的順序以及一些沒有意義的變量:arg0、arg1等等。

但我們又確實需要這部分信息。比如IDE的自動提示,文檔化服務(wù)接口的詳細信息等。

這是因為,這些變量的名字,根本就沒有編譯進class文件中,它不可能憑空產(chǎn)生。

[[333160]]

在JDK 8之后,可以通過在編譯時指定-parameters選項,將方法的參數(shù)名記入class文件,并在運行時通過反射機制獲取相關(guān)信息。

如果你的項目是實用maven構(gòu)建,那么就可以加入幾行配置,追加參數(shù)。

  1. <plugin>   
  2.     <artifactId>maven-compiler-plugin</artifactId>   
  3.     <version>3.8.0</version>   
  4.     <configuration>   
  5.         <source>1.8</source>   
  6.         <target>1.8</target>   
  7.         <encoding>utf8</encoding>   
  8.         <compilerArgs>   
  9.             <arg>-parameters</arg>   
  10.         </compilerArgs>   
  11.     </configuration>   
  12. </plugin>   

如果是用的IDEA等編輯器,也可以通過設(shè)置界面進行配置。不過不推薦這樣,因為你的這些配置不好進行共享。

在普通Java項目里,就可以通過下面的方式來獲取反射數(shù)據(jù)。Method.getParameters這個方法是新加的。

  1. public class Test { 
  2.    
  3.     public static void main(String[] args) throws Exception{ 
  4.         Class clazz = Class.forName("com.test.MethodParameterTest"); 
  5.         Method[] methods = clazz.getMethods(); 
  6.         Constructor[] constructors = clazz.getConstructors(); 
  7.         for (Constructor constructor : constructors) { 
  8.             System.out.println("+++" + constructor.getName()); 
  9.             Parameter[] parameters = constructor.getParameters(); 
  10.             for (Parameter parameter : parameters) { 
  11.                 printParameter(parameter); 
  12.             } 
  13.         } 
  14.    
  15.         System.out.println("------------------"); 
  16.         for (Method method : methods) { 
  17.             System.out.println(method.getName()); 
  18.             Parameter[] parameters = method.getParameters(); 
  19.             for (Parameter parameter : parameters) { 
  20.                 printParameter(parameter); 
  21.             } 
  22.         } 
  23.     } 
  24.    
  25.     private static void printParameter(Parameter parameter) { 
  26.         //參數(shù)名 
  27.         System.out.println("\t\t" + parameter.getName()); 
  28.         //是否在源碼中隱式聲明的參數(shù)名 
  29.         System.out.println("\t\t\t implicit:" + parameter.isImplicit()); 
  30.         //類文件中,是否存在參數(shù)名 
  31.         System.out.println("\t\t\t namePresent:" + parameter.isNamePresent()); 
  32.         //是否為虛構(gòu)參數(shù) 
  33.         System.out.println("\t\t\t synthetic:" + parameter.isSynthetic()); 
  34.         System.out.println("\t\t\t VarArgs:" + parameter.isVarArgs()); 
  35.     } 

下面介紹幾個方法的意義:

isImplicit()

參數(shù)是否為隱式聲明在源文件中,比如內(nèi)部類,默認構(gòu)造函數(shù)(無參)其實在編譯成class時將會把包含它的主類引用作為首個參數(shù),此參數(shù)即為隱式聲明。

如果為true,即表示有JDK編譯器隱式生成在class文件中的方法參數(shù),而source文件中并不可見。常規(guī)的普通方法,此值為false。

isNamePresent()

此參數(shù)在class文件中是否有此參數(shù)名;受制于在編譯時是否指定了“-parameter”,對于指定此參數(shù)的編譯文件,通常為true;對于JDK 內(nèi)部類、默認編譯的類,通常為false;此時你會發(fā)現(xiàn),它們的參數(shù)名通常為表意名稱:arg0、arg1等等,此時為false。

isSynthetic()

是否為“虛構(gòu)”參數(shù),如果為true,表示既不是“顯式”聲明、也不是隱式聲明在源文件中的參數(shù),比如enum類的“values()”、“valueOf(String)”這是編譯器“虛構(gòu)”的系統(tǒng)方法。

在Spring環(huán)境中,由于有工具類的支持,會更加方便一些。

  1. public class SpringTest { 
  2.    
  3.     private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); 
  4.    
  5.    
  6.     public static void main(String[] args) throws Exception{ 
  7.         Class clazz = Class.forName("com.test.MethodParameterTest"); 
  8.         Method[] methods = clazz.getMethods(); 
  9.         for (Method method : methods) { 
  10.             System.out.println(method.getName()); 
  11.             //JDK 1.8 + is better. 
  12.             String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); 
  13.             if (parameterNames == null) { 
  14.                 continue; 
  15.             } 
  16.             for (String pn : parameterNames) { 
  17.                 System.out.println("\t\t" + pn); 
  18.             } 
  19.         } 
  20.     } 

那Java版本低于1.8的時候,又是怎么獲取的呢?我們可以參考Spring的LocalVariableTableParameterNameDiscoverer類。

  1. public String[] getParameterNames(Method method) { 
  2.         Method originalMethod = BridgeMethodResolver.findBridgedMethod(method); 
  3.         return doGetParameterNames(originalMethod); 
  4. @Nullable 
  5. private String[] doGetParameterNames(Executable executable) { 
  6.         Class<?> declaringClass = executable.getDeclaringClass(); 
  7.         Map<Executable, String[]> map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass); 
  8.         return (map != NO_DEBUG_INFO_MAP ? map.get(executable) : null); 

最后就走到了inspectClass方法中。

  1. private Map<Executable, String[]> inspectClass(Class<?> clazz) { 
  2.         InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz)); 
  3.         if (is == null) { 
  4.             // We couldn't load the class file, which is not fatal as it 
  5.             // simply means this method of discovering parameter names won't work. 
  6.             if (logger.isDebugEnabled()) { 
  7.                 logger.debug("Cannot find '.class' file for class [" + clazz + 
  8.                         "] - unable to determine constructor/method parameter names"); 
  9.             } 
  10.             return NO_DEBUG_INFO_MAP; 
  11.         } 
  12.         try { 
  13.             ClassReader classReader = new ClassReader(is); 
  14.             Map<Executable, String[]> map = new ConcurrentHashMap<>(32); 
  15.             classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0); 
  16.             return map; 
  17.         } 
  18.         ... 

可以看到,這種情況下,Spring是通過直接讀取class文件進行解析的。實際上是通過讀取LocalVariableTable中的數(shù)據(jù)進行獲取的。如果你編譯的時候沒有加入這些debug選項,同樣也拿不到方法參數(shù)的具體名稱。

總結(jié)一下

  • Java8以前,讀取Class中的LocalVariableTable屬性表,需要編譯時加入?yún)?shù)-g或者-g:vars 獲取方法局部變量調(diào)試信息;
  • Java8及其以后,通過java.lang.reflect.Parameter#getName即可獲取,但需要編譯時加入?yún)?shù)-parameters參數(shù)。

 

責(zé)任編輯:趙寧寧 來源: 小姐姐味道
相關(guān)推薦

2017-02-05 10:21:10

程序員好問題

2021-10-01 00:02:54

CHAR VARCHARMYSQL

2015-05-05 09:39:57

編程被編程

2020-02-17 21:17:40

www域名主機

2020-06-21 05:55:45

勒索軟件攻擊贖金

2009-11-24 14:21:17

2010-06-08 16:21:46

如何安裝Opensus

2017-06-02 08:48:29

互斥鎖JavaCAS

2010-02-06 11:19:33

C++獲取文件

2018-05-29 09:08:16

vSAN 塊存儲應(yīng)用

2020-08-04 16:56:50

Java方法參數(shù)

2009-11-23 15:10:28

PHP獲取當(dāng)前url

2012-09-13 10:44:32

Web設(shè)計Web分頁架構(gòu)設(shè)計

2020-01-20 14:44:03

云計算架構(gòu)IT

2017-04-25 14:58:02

網(wǎng)絡(luò)可見性漏洞

2010-07-27 11:09:43

設(shè)置NFS

2010-03-18 11:18:54

Java main方法

2009-06-30 13:54:00

名稱空間Java

2009-12-07 19:34:01

PHP函數(shù)可變參數(shù)列表

2009-11-26 09:18:56

PHP函數(shù)參數(shù)傳遞方法
點贊
收藏

51CTO技術(shù)棧公眾號