在JDK 8中可通过反射获得构造函数/方法参数元数据
JDK 8較不為人所知的一項(xiàng)新 功能是在編譯的Java類中包含參數(shù)元數(shù)據(jù)的可選功能[JDK增強(qiáng)建議( JEP ) 118 ]。 此功能允許Java應(yīng)用程序在運(yùn)行時(shí)通過反射訪問此參數(shù)元數(shù)據(jù)信息。
Java Tutorial的Reflection API路徑包括一個(gè)名為“ 獲取方法參數(shù)的名稱”的課程,該課程討論并演示了如何在Java 8中應(yīng)用此新功能。該課程包括一個(gè)示例Java類MethodParameterSpy ,可以對(duì)提供的Java類運(yùn)行該類以指示特征方法和構(gòu)造函數(shù)參數(shù)。 本課還強(qiáng)調(diào)這是一項(xiàng)可選功能,因?yàn)樵?class文件中存儲(chǔ)其他參數(shù)元數(shù)據(jù)會(huì)增加這些文件的大小。 該課程還指出,在某些情況下,參數(shù)名稱包含開發(fā)人員不希望在已編譯的.class文件中使用的敏感信息。
通過將-parameters選項(xiàng)傳遞給javac編譯器,可以將其他參數(shù)元數(shù)據(jù)包含在用Java 8編譯的.class文件中。 當(dāng)一個(gè)人鍵入javac -help時(shí),也會(huì)顯示此-parameters選項(xiàng),如下一個(gè)屏幕快照所示。
該javac的甲骨文技術(shù)說明頁面顯示此附加方法/構(gòu)造函數(shù)的參數(shù)數(shù)據(jù)在運(yùn)行時(shí)可以訪問:在生成的類文件“房屋構(gòu)造函數(shù)和方法的形式參數(shù)名稱,這樣的方法java.lang.reflect.Executable.getParameters從Reflection API可以檢索它們。” 以下代碼片段(名為ParameterDisplayer類)對(duì)此進(jìn)行了演示(重點(diǎn)在displayParametersMetadata(String[])方法上)。
ParameterDisplayer.java
package dustin.examples.jdk8;import static java.lang.System.out; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Parameter;/*** Uses JDK 8 Parameter class to demonstrate metadata related to the parameters* of the methods and constructors of the provided class (includes private,* protected, and public methods, but does not include methods inherited from* parent classes; those classes should be individually submitted).* * @author Dustin*/ public class ParameterDisplayer {private static void displayParametersMetadata(final String[] classesNames){for (final String className : classesNames){try{final Class clazz = Class.forName(className);// Get all class's declared methods (does not get inherited methods)final Method[] declaredMethods = clazz.getDeclaredMethods();for (final Method method : declaredMethods){writeHeader("Method " + method.toGenericString()+ " has " + method.getParameterCount() + " Parameters:");int parameterCount = 0;final Parameter[] parameters = method.getParameters();for (final Parameter parameter : parameters){out.println("\targ" + parameterCount++ + ": "+ (parameter.isNamePresent() ? parameter.getName() : "Parameter Name not provided,")+ (isParameterFinal(parameter) ? " IS " : " is NOT ")+ "final, type " + parameter.getType().getCanonicalName()+ ", and parameterized type of " + parameter.getParameterizedType()+ " and " + (parameter.isVarArgs() ? "IS " : "is NOT ")+ "variable." );}}}catch (ClassNotFoundException cnfEx){out.println("Unable to find class " + className);}}}private static void writeHeader(final String headerText){out.println("\n==========================================================");out.println("= " + headerText);out.println("==========================================================");}/*** Indicate whether provided Parameter is final.* * @param parameter Parameter to be tested for 'final' modifier.* @return {@code true} if provided Parameter is 'final'.*/private static boolean isParameterFinal(final Parameter parameter){return Modifier.isFinal(parameter.getModifiers());}public static void main(final String[] arguments){if (arguments.length < 1){out.println("You must provide the fully qualified name of at least one class.");System.exit(-1);}displayParametersMetadata(arguments);} }我最初考慮過對(duì)JDK的知名類運(yùn)行此類,但是意識(shí)到這并不太有用,因?yàn)檫@些類不太可能是使用-parameters選項(xiàng)構(gòu)建的。 因此,我創(chuàng)建了一個(gè)簡單的示例類來輔助演示。 它稱為ManyMethods然后顯示。
ManyMethods.java
package dustin.examples.jdk8;import java.util.List;/*** Class with numerous methods intended to be used in demonstrating JDK 8's new* Parameter class.* * @author Dustin*/ public class ManyMethods {public ManyMethods() {}private void addArrayOfStrings(String[] strings) {}private void addManyStrings(final String ... strings) {}private void addListOfStrings(final List<String> strings) {}@Overridepublic String toString(){return "ManyMethods";} }接下來的兩個(gè)屏幕快照演示了ManyMethods不使用-parameters選項(xiàng)的情況下編譯的ManyMethods實(shí)例上運(yùn)行ParameterDisplayer 。 最顯著的區(qū)別是,不使用-parameters選項(xiàng)進(jìn)行編譯時(shí),不提供參數(shù)名稱。 同樣,如果沒有-parameters選項(xiàng),則在編譯時(shí)參數(shù)是否為final也沒有可信信息。 在不使用-parameters進(jìn)行編譯的情況下,無論-parameters是否為final , Parameter.getModifiers()方法均不包含final 。
ParameterDisplayer類使用Parameter.isNamePresent()以編程方式標(biāo)識(shí)不存在參數(shù)名稱(當(dāng)未使用-parameters選項(xiàng)進(jìn)行編譯時(shí))。 如果未進(jìn)行檢查,則Parameter.getName()返回的參數(shù)名稱將為“ arg”加上參數(shù)編號(hào)(第一個(gè)參數(shù)為arg0,第二個(gè)參數(shù)為arg1,依此類推)。
ManyMethods類中具有參數(shù)的三個(gè)方法中的ManyMethods具有該參數(shù)的final修飾符。 僅當(dāng)使用-parameters選項(xiàng)編譯類時(shí),才可以通過使用Parameter.getModifiers()進(jìn)行反射來正確識(shí)別這些情況。
略相關(guān)的旁注:Sun / Oracle工具文檔始終由“ windows”頁面和“ solaris”頁面組成,后者通常用于描述特定工具如何在Linux和Unix上的所有版本上工作。 我注意到Java 8文檔對(duì)此進(jìn)行了更改。 該文檔仍然具有“ windows”版本,但是Unix / Linux版本現(xiàn)在其URL中具有“ unix”。 為了說明這一點(diǎn),這里是Java SE 7和Java SE 8 javac工具頁面的URL:
- http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
- http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html
- http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html
- http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html
回到新的(使用Java 8) 參數(shù)類,值得注意的是,存儲(chǔ)此附加參數(shù)元數(shù)據(jù)的已編譯.class文件有所增加。 對(duì)于上面顯示的我的ManyMethods類, .class文件從909字節(jié)擴(kuò)大到961字節(jié)。
像Method一樣, 構(gòu)造 方法擴(kuò)展了Executable ,因此Constructor類享有與Method相同的getParameters方法。 當(dāng)使用這些額外信息顯式編譯代碼時(shí),Java 8將提供有關(guān)方法和構(gòu)造函數(shù)參數(shù)的更多詳細(xì)信息。
翻譯自: https://www.javacodegeeks.com/2014/04/constructormethod-parameters-metadata-available-via-reflection-in-jdk-8.html
總結(jié)
以上是生活随笔為你收集整理的在JDK 8中可通过反射获得构造函数/方法参数元数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 万寿花的功效和作用 万寿花优点是什么
- 下一篇: iphone怎么取消锁屏