前言

在JDK8之前javac编译是不会把构造器和方法的参数名编译进class中,如果需要获取参数名,可以在方法上加上注解,反射获取注解的值从而获取参数名,比如Jackson的@JsonCreator和@JsonProperty 。而JDK8新增了这一个功能,可以直接调用java.lang.reflect.Parameter.getName()获取到,前提是javac需要添加-parameters这个参数。通常来说不建议这样做,因为这会增大.class和在JVM中会占用更多的内存。

正文

代码

直接上代码。

用来打印类信息

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import java.lang.reflect.Parameter;

import static java.lang.System.out;

public class MethodParameterSpy {

private static final String fmt = "%24s: %s%n";

public static void printClassConstructors(Class c) {

Constructor[] allConstructors = c.getConstructors();

out.format(fmt, "Number of constructors", allConstructors.length);

for (Constructor currentConstructor : allConstructors) {

printConstructor(currentConstructor);

}

Constructor[] allDeclConst = c.getDeclaredConstructors();

out.format(fmt, "Number of declared constructors",

allDeclConst.length);

for (Constructor currentDeclConst : allDeclConst) {

printConstructor(currentDeclConst);

}

}

public static void printClassMethods(Class c) {

Method[] allMethods = c.getDeclaredMethods();

out.format(fmt, "Number of methods", allMethods.length);

for (Method m : allMethods) {

printMethod(m);

}

}

public static void printConstructor(Constructor c) {

out.format("%s%n", c.toGenericString());

Parameter[] params = c.getParameters();

out.format(fmt, "Number of parameters", params.length);

for (int i = 0; i < params.length; i++) {

printParameter(params[i]);

}

}

public static void printMethod(Method m) {

out.format("%s%n", m.toGenericString());

out.format(fmt, "Return type", m.getReturnType());

out.format(fmt, "Generic return type", m.getGenericReturnType());

Parameter[] params = m.getParameters();

for (int i = 0; i < params.length; i++) {

printParameter(params[i]);

}

}

public static void printParameter(Parameter p) {

out.format(fmt, "Parameter class", p.getType());

out.format(fmt, "Parameter name", p.getName());

out.format(fmt, "Modifiers", p.getModifiers());

out.format(fmt, "Is implicit?", p.isImplicit());

out.format(fmt, "Is name present?", p.isNamePresent());

out.format(fmt, "Is synthetic?", p.isSynthetic());

}

public static void main(String... args) {

printClassConstructors(ExampleMethods.class);

printClassMethods(ExampleMethods.class);

}

}

包含各种类型方法的类

import java.util.*;

public class ExampleMethods {

public boolean simpleMethod(String stringParam, int intParam) {

System.out.println("String: " + stringParam + ", integer: " + intParam);

return true;

}

public int varArgsMethod(String... manyStrings) {

return manyStrings.length;

}

public boolean methodWithList(List listParam) {

return listParam.isEmpty();

}

public void genericMethod(T[] a, Collection c) {

System.out.println("Length of array: " + a.length);

System.out.println("Size of collection: " + c.size());

}

}

不带-parameters

不带-parameters运行结果:

Number of constructors: 1

public ExampleMethods()

Number of parameters: 0

Number of declared constructors: 1

# 构造器

public ExampleMethods()

Number of parameters: 0

Number of methods: 4

# 方法一

public boolean ExampleMethods.simpleMethod(java.lang.String,int)

Return type: boolean

Generic return type: boolean

Parameter class: class java.lang.String

Parameter name: arg0

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

Parameter class: int

Parameter name: arg1

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

# 方法二

public boolean ExampleMethods.methodWithList(java.util.List)

Return type: boolean

Generic return type: boolean

Parameter class: interface java.util.List

Parameter name: arg0

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

# 方法三

public void ExampleMethods.genericMethod(T[],java.util.Collection)

Return type: void

Generic return type: void

Parameter class: class [Ljava.lang.Object;

Parameter name: arg0

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

Parameter class: interface java.util.Collection

Parameter name: arg1

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

# 方法四

public int ExampleMethods.varArgsMethod(java.lang.String...)

Return type: int

Generic return type: int

Parameter class: class [Ljava.lang.String;

Parameter name: arg0

Modifiers: 0

Is implicit?: false

Is name present?: false

Is synthetic?: false

可以看出Parameter name全都是arg0~argN,因为参数名在编译期已经丢失了。Is name present为false。

带-parameters

maven在pom.xml中添加

org.apache.maven.plugins

maven-compiler-plugin

8

8

-parameters

命令行在javac 后面加 -parameters

运行结果

Number of constructors: 1

public ExampleMethods()

Number of parameters: 0

Number of declared constructors: 1

# 构造器

public ExampleMethods()

Number of parameters: 0

Number of methods: 4

# 方法一

public boolean ExampleMethods.methodWithList(java.util.List)

Return type: boolean

Generic return type: boolean

Parameter class: interface java.util.List

Parameter name: listParam

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

# 方法二

public int ExampleMethods.varArgsMethod(java.lang.String...)

Return type: int

Generic return type: int

Parameter class: class [Ljava.lang.String;

Parameter name: manyStrings

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

# 方法三

public void ExampleMethods.genericMethod(T[],java.util.Collection)

Return type: void

Generic return type: void

Parameter class: class [Ljava.lang.Object;

Parameter name: a

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

Parameter class: interface java.util.Collection

Parameter name: c

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

# 方法四

public boolean ExampleMethods.simpleMethod(java.lang.String,int)

Return type: boolean

Generic return type: boolean

Parameter class: class java.lang.String

Parameter name: stringParam

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

Parameter class: int

Parameter name: intParam

Modifiers: 0

Is implicit?: false

Is name present?: true

Is synthetic?: false

这样就把参数名给打印出来了,Is name present为true。

留个问题

出于好奇,以十六进制打开ExampleMethods的class文件,maven项目在idea中build出来的class不管有没有带-parameters都会把参数名编译进去,但是多了MethodParameters这几个字眼。如下图:

然后尝试直接用javac -parameters编译,打开后

很明显是没有把参数名编译进去的。

好像找不到idea执行build的时候执行了什么,所有我猜测控制java.lang.reflect.Parameter.getName()返回是否真实的参数名就是在于MethodParameters这词,在jvm加载class时识别是否有MethodParameters,而决定是否加载参数名。

这仅是猜测,望大家相告是其真正的原理。

文中也可能存在错误,也望大家指出。

代码来源

上述代码全部来自#参考资料中的Obtaining Names of Method Parameters

参考资料

java 反射 参数名_JAVA 8 反射获取参数名相关推荐

  1. java 反射调用方法_java的反射机制,以及通过反射获取方法,变量等操作

    我们应用会用到反射这个知识点,肯定是想要在运行时得到类的信息,根据类的那些信息去做一些特定的操作.那么,首先无疑就是得到类的信息,在JDK中提供了Class对象来保存类的信息.所以,反射的第一步就是得 ...

  2. java 反射 泛型 构造函数_Java复习——反射和泛型的复习

    反射 Class类 一个类被类加载器加载到内存之中,占有一片区域,这个空间里的内容就是类的字节码,不同的类的字节码是不一样的,这一个个空间页可以使用类来表示,这就是Class类. 根据这个概念可知:不 ...

  3. java 中反射的使用_java中反射的基本使用

    fanShe.java package example5; class fanShe{ /*1.应用在一些通用性比较高的代码中. *2.后面学的框架,大多数都是应用框架来实现的. *3.在框架开发中, ...

  4. java读图片显示到前端_java从前端获取参数添加到图片后返回整张图片

    java从前端获取参数添加到图片后返回整张图片 以后为整个servlet代码,请自行加入到j2ee工程. import java.awt.Color; import java.awt.Font; im ...

  5. java中重载 参数顺序_Java方法中的参数太多,第4部分:重载

    java中重载 参数顺序 期望将过多的参数传递给Java方法的问题之一是,该方法的客户端很难确定它们是否以适当的顺序传递了适当的值. 在以前的文章中,我描述了如何使用自定义类型 , 参数对象和构建器来 ...

  6. java 可变参数方法_Java方法中的参数太多,第7部分:可变状态

    java 可变参数方法 在我的系列文章的第七篇中,有关解决Java方法或构造函数中过多参数的问题 ,我着眼于使用状态来减少传递参数的需要. 我等到本系列的第七篇文章来解决这个问题的原因之一是,它是我最 ...

  7. java 构建者模式_Java方法中的参数太多,第3部分:构建器模式

    java 构建者模式 在我的前两篇文章中,我研究了如何通过自定义类型和参数对象减少构造函数或方法调用所需的参数数量. 在本文中,我将讨论如何使用构建器模式来减少构造器所需的参数数量,并讨论该模式如何甚 ...

  8. java 不定参数方法_java中不定长参数的使用方法

    java中不定长参数的使用方法 不定长参数方法的语法如下:返回值 方法名(参数类型...参数名称) 在参数列表中使用"..."形式定义不定长参数,其实这个不定长参数a就是一个数组, ...

  9. java命令行参数工具_Java方法中的参数太多,第8部分:工具

    java命令行参数工具 在我的系列文章的前七篇文章中,有关处理Java方法中期望的参数过多的内容集中在减少方法或构造函数期望的参数数量的替代方法上. 在本系列的第八篇文章中,我将介绍一些工具,这些工具 ...

最新文章

  1. mysql 2003错误 10055_MYSQL无法连接 提示10055错误的解决方法
  2. [译]ASP.NET Core 2.0 网址重定向
  3. python rtf转txt_将DOC、RTF格式文件批量转为TXT格式文件
  4. LeetCode 862. 和至少为 K 的最短子数组(前缀和+deque单调栈)
  5. ghelper失效_Ghelper账号+网易云音乐领黑胶会员35天
  6. VMware虚拟机文件
  7. python中for循环怎么打开_详解Python中for循环的使用
  8. Android SwipeRefreshLayout 实现下拉刷新2
  9. 线性规划的大M法和非线性规划的拉格朗日乘子法
  10. Modbus转Profinet将英威腾CHF100A变频器接入PROFINET网络
  11. time+dd测试硬盘读写速度
  12. 阿里云服务器搭建ftp服务器
  13. 如何将html改成mht格式,如何编辑mht格式的文件,什么是mht?
  14. 【drawio笔记】在drawio中添加数学公式
  15. citrix VPX 中申请证书的重点
  16. 历史沿革:NFTs在以太坊上的发展之路
  17. 简述docx文档格式-CTF竞赛专用
  18. 《大话数据结构》看书笔记--算法
  19. 2017-2018年度刷题记录
  20. luna16目标检测(记录)

热门文章

  1. 天兔(Lepus)监控邮件推送安装配置
  2. windows环境下封装条件wait和signal
  3. 向SharePoint页面添加后台代码
  4. JavaScript:window.event.srcElement(指触发事件的对象)
  5. leetcode刷题之树(2)
  6. 机器学习导论(张志华):条件期望
  7. 【总结】机器学习划分数据集的几种方法
  8. [云炬创业学笔记]第三章商业创意的发掘与评估测试4
  9. 科大星云诗社动态20210313
  10. 吴恩达《卷积神经网络》精炼笔记(2)-- 深度卷积模型:案例研究