资讯专栏INFORMATION COLUMN

JAVA 8 反射获取参数名

shiweifu / 2926人阅读

摘要:前言在之前编译是不会把构造器和方法的参数名编译进中,如果需要获取参数名,可以在方法上加上注解,反射获取注解的值从而获取参数名,比如的和。带在中添加命令行在后面加运行结果构造器方法一方法二方法三方法四这样就把参数名给打印出来了,为。

前言

在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

参考资料

Obtaining Names of Method Parameters

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76827.html

相关文章

  • Java反射详细介绍

    摘要:通过反射获取带参无返回值成员方法并使用设置安全检查,访问私有构造函数必须创建实例这种不行,注意和方法需要传递参数测试复制这个功能获取私有方法,同样注意和的区别赋予访问权限调用方法。 反射 目录介绍 1.反射概述 1.1 反射概述 1.2 获取class文件对象的三种方式 1.3 反射常用的方法介绍 1.4 反射的定义 1.5 反射的组成 1.6 反射的作用有哪些 2.反射的...

    ingood 评论0 收藏0
  • Java反射机制及API使用

    摘要:有一个参数的构造方法姓名有多个参数的构造方法姓名年龄这的执行效率有问题,以后解决。私有构造方法私有的构造方法年龄反射获取对象的三种方式通过对象名方法获取通过类名方式获得通过方法获得在运行期间,一个类,只有一个对象产生。 原文地址 反射简单来说,就是动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道并获取这个类的所有属性和方法。 Java反...

    vibiu 评论0 收藏0
  • 进击的Android工程师之Java基础: 反射

    摘要:不包含父类或父接口的方法返回,根据方法名和类型获取。类或接口的及父类父接口公共成员方法。是的返回方法名,不包括修饰符,参数和返回值。打印打印抛出因为的访问权限为抛出,因为是父类的方法。 反射机制呢就是在程序运行时,动态的获取类(class),类的方法(method)属性(field)等。主要的注意点就是程序运行时动态的获取。这里主要是从代码的角度来讲解Java反射。在使用中我们用的较多...

    aaron 评论0 收藏0
  • 1、类加载器 2、反射构造方法 3、反射成员变量 4、反射成员方法 5、反射配置文件运行类中的方法

    摘要:通过反射获取无参构造方法并使用得到无参构造方法获取所有的修饰的构造方法。如果方法没有返回值,返回的是反射获取空参数成员方法并运行代码演示反射获取成员方法并运行获取对象中的成员方法获取的是文件中的所有公共成员方法包括继承的类是描述 01类加载器 * A.类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。  ...

    Profeel 评论0 收藏0
  • Reflection:Java反射机制基础

    摘要:反射机制是什么反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性这种动态获取的信息以及动态调用对象的方法的功能称为语言的反射机制反射机制能做什么反射机制主要提供了以下功 反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种...

    hizengzeng 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<