java反射无法获取方法参数的真正名字

java的变量名,函数名等在编译时并不会按照程序员自己给的名字编译,相反,编译器会一一做替换,比如你的public void fun( String str);中的变量名str在编译之后就不叫str了,而可能是arg0,arg1.

parameter反射实例

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

public class Constructors {
    public Constructors() {
        System.out.println("无参构造函数");
    }

    public Constructors( String s) {
        System.out.println("有1个参构造函数");
        System.out.println(s);
    }

    public Constructors(final String s, int num) {
        System.out.println("有2个参构造函数");
        System.out.println(s);
    }

    public static void main(String[] args) {
        try {
            // 1、获取指定构造方法
            Class clazz = Class.forName("reflect.Constructors");
            // 无参构造函数生成对象
            clazz.newInstance();
            //Constructor con = clazz.getConstructor(String.class, int.class);
            //Constructors cons = (Constructors) con.newInstance("获取构造器实例化对象", 4);
            // 2、 获取全部构造方法
            Constructor[] conarr = clazz.getConstructors();
            for (Constructor constructor : conarr) {
                // 获取每个构造函数的参数字节码对象
                Class[] parameterTypes = constructor.getParameterTypes();
                for (Class pclass : parameterTypes) {
                    System.out.print(pclass.getName() + ", ");
                }
                System.out.println();
                // 获取构造参数对象
                Parameter[] parameters = constructor.getParameters();
                for (Parameter parameter : parameters) {
                     System.out.println("通过parameter.getModifiers()获取参数修饰符:" + (parameter.getModifiers()));
                     System.out.println("通过parameter.getName()获取参数名:" + parameter.getName()); 
                     System.out.println("通过parameter.getParameterizedType()获取参数化类型(泛型):" + parameter.getParameterizedType()); 
                     System.out.println("通过parameter.toString()获取参数的字符串描述:" + parameter.toString());
                     System.out.println("通过parameter.isSynthetic()判断参数是否是合成的:" + parameter.isSynthetic()); 
                     System.out.println("通过parameter.isImplicit()判断参数是否是隐式的:" + parameter.isImplicit()); 
                     System.out.println("通过parameter.isNamePresent()判断参数是否以类文件名命名:" + parameter.isNamePresent()); 
                     System.out.println("通过parameter.isVarArgs()判断参数是否是可变的:" + parameter.isVarArgs() + "\n");
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出结果:

无参构造函数
java.lang.String, int, 
通过parameter.getModifiers()获取参数修饰符:0
通过parameter.getName()获取参数名:arg0
通过parameter.getParameterizedType()获取参数化类型(泛型):class java.lang.String
通过parameter.toString()获取参数的字符串描述:java.lang.String arg0
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:false
通过parameter.isVarArgs()判断参数是否是可变的:false

通过parameter.getModifiers()获取参数修饰符:0
通过parameter.getName()获取参数名:arg1
通过parameter.getParameterizedType()获取参数化类型(泛型):int
通过parameter.toString()获取参数的字符串描述:int arg1
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:false
通过parameter.isVarArgs()判断参数是否是可变的:false

java.lang.String, 
通过parameter.getModifiers()获取参数修饰符:0
通过parameter.getName()获取参数名:arg0
通过parameter.getParameterizedType()获取参数化类型(泛型):class java.lang.String
通过parameter.toString()获取参数的字符串描述:java.lang.String arg0
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:false
通过parameter.isVarArgs()判断参数是否是可变的:false

可以看到,参数修饰符的值无法获取,参数的名字被改为arg0等
解决方法,jdk版本换为1.8,在myeclipse的首选项中做如下配置

《java反射无法获取方法参数的真正名字》

重新编译运行,输出为

无参构造函数
java.lang.String, int, 
通过parameter.getModifiers()获取参数修饰符:16
通过parameter.getName()获取参数名:s
通过parameter.getParameterizedType()获取参数化类型(泛型):class java.lang.String
通过parameter.toString()获取参数的字符串描述:final java.lang.String s
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:true
通过parameter.isVarArgs()判断参数是否是可变的:false

通过parameter.getModifiers()获取参数修饰符:0
通过parameter.getName()获取参数名:num
通过parameter.getParameterizedType()获取参数化类型(泛型):int
通过parameter.toString()获取参数的字符串描述:int num
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:true
通过parameter.isVarArgs()判断参数是否是可变的:false

java.lang.String, 
通过parameter.getModifiers()获取参数修饰符:0
通过parameter.getName()获取参数名:s
通过parameter.getParameterizedType()获取参数化类型(泛型):class java.lang.String
通过parameter.toString()获取参数的字符串描述:java.lang.String s
通过parameter.isSynthetic()判断参数是否是合成的:false
通过parameter.isImplicit()判断参数是否是隐式的:false
通过parameter.isNamePresent()判断参数是否以类文件名命名:true
通过parameter.isVarArgs()判断参数是否是可变的:false

其中Parameter.isNamePresent() 来验证参数名是不是可用。之前全是false,现在全是true。并且获取了参数的真实名字和参数修饰符的值。

参数修饰符

  • PUBLIC: 1 (二进制 0000 0001)
  • PRIVATE: 2 (二进制 0000 0010)
  • PROTECTED: 4 (二进制 0000 0100)
  • STATIC: 8 (二进制 0000 1000)
  • FINAL: 16 (二进制 0001 0000)
  • SYNCHRONIZED: 32 (二进制 0010 0000)
  • VOLATILE: 64 (二进制 0100 0000)
  • TRANSIENT: 128 (二进制 1000 0000)
  • NATIVE: 256 (二进制 0001 0000 0000)
  • INTERFACE: 512 (二进制 0010 0000 0000)
  • ABSTRACT: 1024 (二进制 0100 0000 0000)
  • STRICT: 2048 (二进制 1000 0000 0000)

Modifier.toString

将以上代码中的(parameter.getModifiers()))改为
Modifier.toString(parameter.getModifiers()));

那么输出将变成

...
通过parameter.getModifiers()获取参数修饰符:final
...
通过parameter.getModifiers()获取参数修饰符:
...
通过parameter.getModifiers()获取参数修饰符:
...

Modifier.toString将变量修饰符的数值转换为字符

点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注