JDK 8较不为人所知的一项新 功能是在编译的Java类中包含参数元数据的可选功能[JDK增强建议( JEP ) 118 ]。 此功能允许Java应用程序在运行时通过反射访问此参数元数据信息。

Java Tutorial的Reflection API路径包括一个名为“ 获取方法参数的名称”的课程,该课程讨论并演示了如何在Java 8中应用此新功能。该课程包括一个示例Java类MethodParameterSpy ,可以对提供的Java类运行该类以指示特征方法和构造函数参数。 本课还强调这是一项可选功能,因为在.class文件中存储其他参数元数据会增加这些文件的大小。 该课程还指出,在某些情况下,参数名称包含开发人员不希望在已编译的.class文件中使用的敏感信息。

通过将-parameters选项传递给javac编译器,可以将其他参数元数据包含在用Java 8编译的.class文件中。 当一个人键入javac -help时,也会显示此-parameters选项,如下一个屏幕快照所示。

该javac的甲骨文技术说明页面显示此附加方法/构造函数的参数数据在运行时可以访问:在生成的类文件“房屋构造函数和方法的形式参数名称,这样的方法java.lang.reflect.Executable.getParameters从Reflection API可以检索它们。” 以下代码片段(名为ParameterDisplayer类)对此进行了演示(重点在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);}
}

我最初考虑过对JDK的知名类运行此类,但是意识到这并不太有用,因为这些类不太可能是使用-parameters选项构建的。 因此,我创建了一个简单的示例类来辅助演示。 它称为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";}
}

接下来的两个屏幕快照演示了ManyMethods不使用-parameters选项的情况下编译的ManyMethods实例上运行ParameterDisplayer 。 最显着的区别是,不使用-parameters选项进行编译时,不提供参数名称。 同样,如果没有-parameters选项,则在编译时参数是否为final也没有可信信息。 在不使用-parameters进行编译的情况下,无论-parameters是否为final , Parameter.getModifiers()方法均不包含final

ParameterDisplayer类使用Parameter.isNamePresent()以编程方式标识不存在参数名称(当未使用-parameters选项进行编译时)。 如果未进行检查,则Parameter.getName()返回的参数名称将为“ arg”加上参数编号(第一个参数为arg0,第二个参数为arg1,依此类推)。

ManyMethods类中具有参数的三个方法中的ManyMethods具有该参数的final修饰符。 仅当使用-parameters选项编译类时,才可以通过使用Parameter.getModifiers()进行反射来正确识别这些情况。

略相关的旁注:Sun / Oracle工具文档始终由“ windows”页面和“ solaris”页面组成,后者通常用于描述特定工具如何在Linux和Unix上的所有版本上工作。 我注意到Java 8文档对此进行了更改。 该文档仍然具有“ windows”版本,但是Unix / Linux版本现在其URL中具有“ unix”。 为了说明这一点,这里是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) 参数类,值得注意的是,存储此附加参数元数据的已编译.class文件有所增加。 对于上面显示的我的ManyMethods类, .class文件从909字节扩大到961字节。

像Method一样, 构造 方法扩展了Executable ,因此Constructor类享有与Method相同的getParameters方法。 当使用这些额外信息显式编译代码时,Java 8将提供有关方法和构造函数参数的更多详细信息。

翻译自: https://www.javacodegeeks.com/2014/04/constructormethod-parameters-metadata-available-via-reflection-in-jdk-8.html

在JDK 8中可通过反射获得构造函数/方法参数元数据相关推荐

  1. jdk1.8 ::构造函数_在JDK 8中可通过反射获得构造函数/方法参数元数据

    jdk1.8 ::构造函数 JDK 8较不广为人知的新 功能之一是在已编译的Java类中包含参数元数据的可选功能[JDK增强建议( JEP ) 118 ]. 此功能允许Java应用程序在运行时通过反射 ...

  2. JDK 8中方便的新地图默认方法

    Map接口在JDK 8中提供了一些方便的新方法 . 因为我在本文中介绍的Map方法是作为默认方法实现的,所以Map接口的所有现有实现都享有默认方法中定义的默认行为,而无需任何新代码. 这篇文章中介绍的 ...

  3. Java中注解与反射的使用方法及场景,强行解释一波!

    作者:BudingCode blog.csdn.net/m0_55221239/article/details/115025182 注解 注解定义 Java 注解(Annotation)又称 Java ...

  4. python 函数参数枚举_Python中的枚举:如何在方法参数中强制执行

    Python是动态的和鸭子类型 – 变量可以改变类型,你不能强制类型的方法. 但是,您可以使用isinstance()检查方法体中的类型. instance()将允许用户子类化枚举以便将来扩展. 例如 ...

  5. java反射调用接口方法参数_Java反射调用某个类的方法(带参数和不带参数)

    不多说,直接贴代码,不懂查API,现在就列取要用的方法和类. Class类: public Method getDeclaredMethod(String name, Class>... par ...

  6. 一文汇总 JDK 5 到 JDK 15 中的牛逼功能!

    前言 JDK 16 马上就要发布啦(预计 2021.3.16 日发布),所以在发布之前,让我们先来回顾一下 JDK 5-15 的新特性吧,大家一起学起来~ Java 5 新特性 1. 泛型 泛型本质是 ...

  7. Java中的灵魂-反射机制

    全文都是转载的嗑嗑磕嗑瓜子的猫这位大神的文章,写的非常好,转载过来主要是想将好的知识保存下来方便以后再查阅.原文请点这 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? ...

  8. JDK 8 中的新特性

    目录 JDK 8 中的新特性 JDK 8 中的新特性 JDK 版本说明 JDK 8 版本说明 Java Platform, Standard Edition 8 是一个拥有丰富特性的主要版本.本文档总 ...

  9. laravel mysql注入_laravel中如何利用反射实现依赖注入

    依赖注入 在一个类中经常会依赖于其他的对象,先看一下经典的写法 class Foo { public $bar; public function __construct() { $this->b ...

最新文章

  1. IP地址与网络上的其他系统有冲突
  2. [Java基础]并发修改异常
  3. Hadoop记录-hadoop2.x常用端口及定义方法
  4. 制造业如何应用大数据
  5. IDEA 的这款插件真是逆天了,代码那都不是事!
  6. redis-实现排行榜
  7. 设计模式在游戏中的应用--模板方法(七)
  8. 阿里巴巴矢量图标库的使用
  9. 5阶无向完全图_离散数学图论答案
  10. 如何区分前后端bug
  11. (第二章)HTML基本标记
  12. tomcat加白名单_[WebServer] Tomcat 配置访问限制:访问白名单和访问黑名单
  13. Sasha and a Bit of Relax K倍区间 (前缀和异或 前缀和计数 思维)
  14. Linux文件目录管理、文件内容查看以及文件内容查询命令(详细命令)
  15. RTMP协议和RTSP协议的区别
  16. Symantec Backup Exec恢复数据库
  17. 无心剑中译兰斯顿·休斯《梦想》
  18. 从材料硕士到算法工程师的转行之路
  19. 编程实现AdaBoost算法
  20. java将图片均匀分成9份,怎样把一张图片快速切成平均等分/切图? - 杂谈

热门文章

  1. java实现验证码3秒刷新一次
  2. python股票自动买卖视频教程_十分钟学会用Python交易股票
  3. es6箭头函数(墙裂推荐)
  4. no [query] registered for [filtered] in es7 的解决方法
  5. ui自动化测试测试报告_您需要了解的有关UI测试的所有信息
  6. ibm liberty_使用Open Liberty的开发模式最大程度地缩短周转时间
  7. spring的bean范围_Spring Bean范围
  8. json api_JSON模式在构建和部署API中的作用
  9. 内存 增量数据持久_内存中数据模型和大数据持久性
  10. java restful_Java EE中的RESTful计时器